Манипуляции со строками типа Подстановка строк в математическом выражении - PullRequest
3 голосов
/ 23 ноября 2010

Представьте себе что-то вроде

exp(49/200)+(x-49/200)

Я хочу передать в качестве аргумента функции "roundn" любую операцию, которая не является сложением или вычитанием Таким образом, мое выражение стало

roundn(exp(roundn(49/200, n)), n) + (x - roundn(49/200, n)

Хорошо, выражение, которым я хочу манипулировать, таково:

exp(49/200)+exp(49/200)*(x-49/200)+1/2*exp(49/200)*(x-49/200)^2+1/6*exp(49/200)*(x-49/200)^3+1/24*exp(49/200)*(x-49/200)^4+1/120*exp(49/200)*(x-49/200)^5+1/720*exp(49/200)*(x-49/200)^6+1/5040*exp(49/200)*(x-49/200)^7+1/40320*exp(49/200)*(x-49/200)^8+1/362880*exp(49/200)*(x-49/200)^9+1/3628800*exp(49/200)*(x-49/200)^10+1/39916800*exp(49/200)*(x-49/200)^11

Ответы [ 4 ]

6 голосов
/ 23 ноября 2010

Может быть, вы думаете, что хотите это сделать, но на самом деле вы не хотите этого делать. Новые Python обычно думают, что им нужно округлить числа с плавающей запятой, потому что при оценке они получают неожиданные результаты (например, 1,0 / 10 = 0,100000000000001). Вместо того, чтобы делать глупые подстановки в вашем выражении, я просто создал переменную для round(49/200,n) и немного очистил формат. Также exp(49/200) не нужно оценивать 13 раз, просто сделайте это один раз и обратитесь к вычисленному значению.

zz = round(49/200,n)
e_zz = exp(zz)
ans = (e_zz + 
    e_zz * (x-zz) +
    1/2 * e_zz * (x-zz)**2 +
    1/6 * e_zz * (x-zz)**3 +
    1/24 * e_zz * (x-zz)**4 +
    1/120 * e_zz * (x-zz)**5 +
    1/720 * e_zz * (x-zz)**6 +
    1/5040 * e_zz * (x-zz)**7 +
    1/40320 * e_zz * (x-zz)**8 +
    1/362880 * e_zz * (x-zz)**9 +
    1/3628800 * e_zz * (x-zz)**10 +
    1/39916800 * e_zz * (x-zz)**11)

Повышение e до округленного числа почти никогда не подходит. Аналогично для повышения округленного числа до 11-й степени. (Обратите внимание, что в Python оператор возведения в степень равен **, а не ^.)

Отредактированный : Если бы С.Лотт не предложил алгебраическое упрощение, я бы оставил это как есть. Но * e_zz может быть выделен из каждого термина, давая более простое (и, вероятно, более быстрое):

zz = round(49/200,n)
e_zz = exp(zz)
ans = e_zz * (1 + 
    (x-zz) +
    1/2 * (x-zz)**2 +
    1/6 * (x-zz)**3 +
    1/24 * (x-zz)**4 +
    1/120 * (x-zz)**5 +
    1/720 * (x-zz)**6 +
    1/5040 * (x-zz)**7 +
    1/40320 * (x-zz)**8 +
    1/362880 * (x-zz)**9 +
    1/3628800 * (x-zz)**10 +
    1/39916800 * (x-zz)**11)
2 голосов
/ 30 ноября 2010

Используйте это

http://sympy.org/

1 голос
/ 23 ноября 2010

Интересно, это то, что вам нужно:

Если ваше исходное уравнение находится в строковой переменной eq, вы можете создать новые уравнения, используя replace метод строк:

eq.replace('49/200', 'roundn(49/200,n)')

и подобное выражение может поместить roundn вокруг функции exp() (возможно, здесь понадобится изящное регулярное выражение).

0 голосов
/ 23 ноября 2010

Вы можете указать каждое совпадение, скажем, p=re.compile(r'\d+/\d+') с выводом функции округления. К вашему сведению, аппроксимация такого количества терминов в вашем выражении даст результат, который не обязательно будет очень близок к фактическому результату, в зависимости от того, сколько цифр вы округлите.

...