Уведомления

Группа в Telegram: @pythonsu

#1 Март 29, 2010 20:20:39

villager
От:
Зарегистрирован: 2008-11-04
Сообщения: 111
Репутация: +  0  -
Профиль   Отправить e-mail  

Вычисление формул

Делаю генератор отчетов. А там формулы.
типа a*3+b*(c+d)
причем a,b и т.д. не обязательно переменные python, это могут быть и поля таблицы БД
собрался было разбирать формулу, строить деревья…
Но обошелся малой кровью:

# -*- coding: utf-8 -*-
import re
class zzCalc():
dataDict={}#словарь для переменных
def userData(self, key):#метод для извлечения данных
return 0
def myCa(self, para):#вычислятор переменных
rez=0
try:
rez=eval(para)
except:
if self.dataDict.has_key(para):#
rez=self.dataDict[para]
else:
rez=self.userData(para)
finally:
return rez
def calc(self, expr): #расчет формулы
expr="+"+expr+"+"
oprs="[/\(\)\+\*\-\s]"
vars=re.split(oprs,expr)
for v in vars:#удалим все, что начинается с точки
if v<>"":
if v[0]==".": del vars[vars.index(v)]
for x in vars:
if x<>"":
d=re.findall("%s%s%s" % (oprs, x, oprs),expr)
for y in d:
newop=y.replace(x, "self.myCa('%s')" % x)
expr=expr.replace(y,newop)
expr=expr[1:-1]
rez=0
try:
rez=eval(expr)
finally:
return rez
####################################################
class uu():
d=12
def m(self, i=1): return i**2
def s(self, i=1): return "*io %s **" % i
def aa(p):return -p*64

u=uu()

def myData(para):
if para=="c":
return 1
else:
return 0

mc=zzCalc()
mc.userData=myData
mc.dataDict["a"]=1
mc.dataDict["b"]=1
proba113=95
print mc.calc("1+1*9/3+u.d")
print mc.calc("u.d+a*b*c")
print mc.calc("proba113")
print mc.calc("u.m(3)")
может кому пригодится…
можно использовать для встроенного калькулятора…



Офлайн

#2 Март 29, 2010 21:55:55

sypper-pit
От: Ulan-Ude(msk)
Зарегистрирован: 2009-01-30
Сообщения: 1102
Репутация: +  6  -
Профиль   Отправить e-mail  

Вычисление формул

спасибо , учту может и пригодится

Офлайн

#3 Сен. 18, 2010 22:09:24

villager
От:
Зарегистрирован: 2008-11-04
Сообщения: 111
Репутация: +  0  -
Профиль   Отправить e-mail  

Вычисление формул

попытка использовать первый вариант в боевых условиях выявила недостатки
поэтому вариант 2:

# -*- coding: utf-8 -*-
import parser
import re
#функция извлечения данных
def myData(var):
if var=="a": return 35
elif var=="b": return 99
elif var=="c": return 9
elif var=="hh": return 1
else: return 9999
#тестовые функции, переменные и классы
class ccl():
a=10
b=2
def c(self, s): return 65*s

def fun(a, lst):
return a+lst[1]

cl=ccl()
li=[1, 2, 3, 4]
a=22222333

#тестовое выражение
e="a+b+[1,2,3][2]+fun(a,[1,9])+cl.a+cl.c(gd)+int('985')+c-f+li[hh]+u+{1:1,dd:f}[1]+ccl.b"
ee="+"+e+" "
#выделение имен
for x in parser.suite(e).compile().co_names:
#отбросим имена функций, объектов и классов
rr=re.findall(r"[\(\s\+\-\*\/\^\[{,\:]%s[$\+\-\*\\,\s\]\}\:\)]" % x, ee)
if rr<>[]:
if x not in locals():
#создадим недостающую переменную
exec("%s=myData('%s')" % (x, x))
#преобразуем строку с расшифровкой
for z in rr:
ee=ee.replace( z, (z.replace(x, "%s")) % eval(x))
#Печать преобразованного выражения (иногда в отчетах полезно показать, из чего состоит сумма)
print ee[1:-1]
#печать результата
print eval(e)



Офлайн

#4 Янв. 15, 2011 10:53:37

xa4a
От:
Зарегистрирован: 2008-05-28
Сообщения: 12
Репутация: +  1  -
Профиль   Отправить e-mail  

Вычисление формул

Лучше так: http://paste.in.ua/1630/



Офлайн

#5 Янв. 22, 2011 01:49:41

villager
От:
Зарегистрирован: 2008-11-04
Сообщения: 111
Репутация: +  0  -
Профиль   Отправить e-mail  

Вычисление формул

супер!
спасибо



Офлайн

Board footer

Модераторировать

Powered by DjangoBB

Lo-Fi Version