0

我从数据库中得到一些模型

f(t)=(2.128795454425367)+(208.54359721863273)*t+(26.098128487929266)*t^2+(3.34369909584111)*t^3+(-0.3450228278737971)*t^4+(-0.018630757967458885)*t^5+(0.0015029038553239819)*t^6;

其中有些是字符串。

我需要评估此功能t in range(1, 13)

现在我必须手动复制这些函数并运行它们

   print [1.2381648958643592 + \
          153.55656654019816 * t +\
          22.99318731025164 * (t**2) +\
          11.060577906796075 * (t**3) +\
          -1.3465054084767891 * (t**4) + \
          0.016926765998876842 * (t**5) +\
          0.001500086893490721 * (t**6) for t in range(1, 13)]

有没有更好的方法在 python 中做到这一点?

4

5 回答 5

1

如果性能不是一个主要问题——如果你只在 12 点上评估它,我怀疑不是——那么你可以利用方便的sympy库为你做很多工作。例如:

>>> import sympy
>>> sympy.sympify("t**5 - t + 3")
t**5 - t + 3
>>> sympy.sympify("t**5 - t + 3").subs({"t": 10})
99993

我们可以将其包装在一个返回函数的函数中:

import sympy

def definition_to_function(s):
    lhs, rhs = s.split("=", 1)
    rhs = rhs.rstrip('; ')
    args = sympy.sympify(lhs).args
    f = sympy.sympify(rhs)
    def f_func(*passed_args):
        argdict = dict(zip(args, passed_args))
        result = f.subs(argdict)
        return float(result)
    return f_func

然后我们可以将其应用到正则表达式无法触及的更复杂的情况下:

>>> s = "f(t)=(2.128795454425367)+(208.54359721863273)*t+(26.098128487929266)*t^2+(3.34369909584111)*t^3+(-0.3450228278737971)*t^4+(-0.018630757967458885)*t^5+(0.0015029038553239819)*t^6;"
>>> f = definition_to_function(s)
>>> f(0)
2.128795454425367
>>> f(10)
4230.6764921149115
>>> f = definition_to_function("f(a,b,c) = sin(a)+3*b-4*c")
>>> f(1,2,3)
-5.158529015192103
>>> import math
>>> math.sin(1)+3*2-4*3
-5.158529015192103
于 2012-12-05T23:07:55.150 回答
0

如果要解析“函数”字符串,可以执行以下操作:

import re

s = "f(t)=(2.128795454425367)+(208.54359721863273)*t+(26.098128487929266)*t^2\
    +(3.34369909584111)*t^3+(-0.3450228278737971)*t^4+(-0.018630757967458885)*t^5\
    +(0.0015029038553239819)*t^6;"

def f(t):
    l = map(float, re.findall("-?\\d+\\.\\d+", s))
    return sum(b * t**a for a,b in enumerate(l))

print map(f, xrange(1,13))
[239.75206957484252,544.337732955938,921.544112756058,1366.6221363666925,1864.8848673959649,2393.2591324279497,2922.9192385578326,3423.0027817028927,3865.4085456893295,4230.676492114911,4514.949840987468,4738.019242139209]

这种方法假定函数字符串将始终采用以下形式

c0 + c1 t + c2 t^2 + c3 t^4 + ... cn t^(n+1)

并通过从字符串中提取浮点数并使用它们生成实际的 Python 函数来工作。

于 2012-12-05T22:22:52.263 回答
0

您可以将函数作为 python expersion 存储在数据库中,当您获取字符串时,只需执行类似 eval(funcstr.replace('x', 'yvalue')) 的操作。

给你看一个例子:

funcstr = '2*x+5'
evalpoint = funcstr.replace('x', '5')
val = eval(funcstr)

此时 val 应评估为 15

于 2012-12-05T22:30:21.893 回答
0

正如 NPE 所说,这里的正确答案是为您的表达式语言编写一个解析器(和简单的解释器)。

或者,更好的是,如果可能的话,首先在 Python 中生成表达式,而不是使用与 Python 的子集几乎但不完全兼容的语言。

或者,更好的是,如果该语言只是表示多项式系数列表的一种方式,只需将其表示为系数列表,这将比任何实际的通用语言更容易解析。例如,假设数据库保存了这个:

2.128795454425367, 208.54359721863273, 26.098128487929266, 3.34369909584111, -0.3450228278737971, -0.018630757967458885, 0.0015029038553239819

然后,要在 Python 中执行它,你可以这样做:

def eval_polynomial(polynomial, value):
    coefficients = [float(x.strip()) for x in polynomial.split(',')]
    return sum(coefficient * (value**exponent) 
               for exponent, coefficient in enumerate(coefficients))

然后:

>>> [eval_polynomial(expr, t) for t in range(1, 13)]

但是,如果您真的非常想在不更改数据库中的内容的情况下执行此操作,则可以将其转换为 Python 表达式并对其进行评估:

>>> expr = 'f(t)=(2.128795454425367)+(208.54359721863273)*t+(26.098128487929266)*t^2+(3.34369909584111)*t^3+(-0.3450228278737971)*t^4+(-0.018630757967458885)*t^5+(0.0015029038553239819)*t^6;'
>>> removef = re.sub(r'f\((\w+)\)=', 'lambda \1: ', expr)
>>> fixpower = re.sub(r'(\w+)\^(\d+)', r'(\1**\2)', removef)
>>> nosemi = fixpower.replace(';', '')
>>> func = eval(nosemi)
>>> [func(t) for t in range(1, 13)]
[239.75206957484252, 544.337732955938, 921.544112756058, 1366.6221363666925, 1864.8848673959649, 2393.2591324279497, 2922.9192385578326, 3423.0027817028927, 3865.4085456893295, 4230.676492114911, 4514.949840987468, 4738.019242139209]

但同样,您可能不想这样做。

而且,如果你这样做了,你可能想编写一个适用于你的实际语言的转换器,而不是基于一个例子对你的语言进行暗中猜测......</p>

于 2012-12-05T22:33:33.093 回答
0

如果您信任您的来源,您可以使用 regex 和 eval 来执行此操作:

# deletes the simicolon and everything before the space
my_str = start_str.split('=')[1][:-1]
# change ^ to ** because that's the squared operator
my_str = re.sub('\^', '**', my_str)
# substitute the t for the numbers 1 to 13 and evaluate the string
results = [eval(re.sub('t', str(t), my_str)) for t in range(1,13)]
于 2012-12-05T22:40:01.093 回答