0

(Sorry for my poor English:)

I know that I can use eval to calculate the result of a mathematical expression.

However, this is not accurate(e.g: 0.3-0.2 != 0.1). After searching, I found I can use Fraction or some other methods to calculate.

But I didn't find out how to use these methods to directly calculate a string expression. For example, Fraction('239/3289') is correct but I can't use Fraction('(239/3289+392)/(12+993)').

Is there a simple way to accurately calculate an mathematical expression?

edit: Actually I'm just wondering how to parse such a formula and return the result in Fraction instead of splitting the string and using Fraction(Fraction('239/3289') + 392, 12 + 993)...Does someone know how to do it?

ncr
  • 3
  • 2
  • @VincenzoLaSpesa Yes, I'm just wondering how to parse such a formula and return the result in Fraction instead of splitting the string and using Fraction(Fraction('239/3289') + 392, 12 + 992). – ncr May 16 '20 at 11:18
  • See https://stackoverflow.com/questions/588004/is-floating-point-math-broken – Barmar May 16 '20 at 11:22
  • to get correct result you would have to convert every number to Franction before you use it - `Fraction('0.3') - Fraction('0.2') == Fraction('0.1')` gives `True`. Probably you would have to write own parser to convert it to `Franction` automatically - ie [PLY (Python Lex-Yacc)](https://www.dabeaz.com/ply/) – furas May 17 '20 at 05:21

2 Answers2

0

Try math.isclose and cmath.isclose as suggested here

Let's try
  • 1,044
  • 9
  • 20
  • I do actually want to compare whether two expressions are exactly equal and wonder how to calculate the result accurately...But anyway I'll do that like this, it's just that I'm afraid it's not accurate. Thanks for your answer. – ncr May 16 '20 at 10:51
  • @ncr If you use floating point, you can't expect "exactly equal", because floating point is an approximation -- it introduces errors. – Barmar May 16 '20 at 11:03
  • @Barmar Yes, I'm just wondering how to parse such a formula and return the result in Fraction instead of splitting the string and using Fraction(Fraction('239/3289') + 392, 12 + 992). – ncr May 16 '20 at 11:20
  • You can't. Once you use floating point you lose accuracy and can't get it back. – Barmar May 16 '20 at 11:21
  • I've known this for a long time. In other words, I just want to know how to convert '(239 / 3289 + 392) / (12 + 993)' into Fraction(Fraction('239 / 3289') + 392, 12 + 993) and output the result. Maybe my poor English caused misunderstanding....very sorry. – ncr May 16 '20 at 11:31
  • @Barmar Why doesn't my vote show...I can only thank you here – ncr May 16 '20 at 11:34
0

The argument to Fraction is not an arbitrary expression, it's just for creating one fraction. You can then use that like a number in a more general expression.

Fraction(Fraction('239/3289') + 392, 12 + 992)
Barmar
  • 741,623
  • 53
  • 500
  • 612
  • But what I get is an uncertain and very complex string with many numbers and operators. It's difficult to split the string... – ncr May 16 '20 at 10:18
  • What are you expecting? When you add fractions together you get complex fractions. – Barmar May 16 '20 at 10:24
  • Actually I wanted to compare if results of two complex expressions constructed in some way are exactly equal, so I wondered how to get the accurate result. But anyway thanks for your answer. I'll do that by using math.isclose. – ncr May 16 '20 at 10:54
  • You can use `==` with this, it will tell you that. – Barmar May 16 '20 at 10:55
  • yes, but it have errors. Sometimes it doesn't work. – ncr May 16 '20 at 10:58
  • >>> 0.3-0.2==0.1 False – ncr May 16 '20 at 10:58
  • That's floating point. It should work correctly with fractions. – Barmar May 16 '20 at 11:01