Mathematics, working with floats (or fractions)

Hi,
this will be maybe a repetitive question regarding how to deal with floats, but anyway:
having the following expression: ((1 - 1/6) / (1/12 + 1/8))
If I type it to google I get 4.
If I type it to spreadsheet (of any provider) still I get the result 4.
If I type it to Python, I get 4.000000000000001.

I wonder what would be the correct approach if I wanted the output to be same as from google or spreadsheet?

ChatGPT suggests, one can use sympy:

import sympy

sympy.simplify((1 - 1/6) / (1/12 + 1/8))

this returns 4.0 (in jupyter notebook),

or 4.00000000000000 when used with print function:
print(sympy.simplify((1 - 1/6) / (1/12 + 1/8)))

But we still get the zero after floating point (whether one or many)…

I’m thinking that probably one can also use decimal or fractions libraries here?

Just how to make Python return just number 4 ? (as Google or Excel does)…

Correct depends on what you want.
4.000000000000001 is the correct result, when computing with float.

I wouldn’t trust Excel, even when it gives a correct result.

If your only goal is to get 4, you could do int(((1 - 1/6) / (1/12 + 1/8))).

If you want an exact result, you need to perform the actual computation of ((1 - 1/6) / (1/12 + 1/8)) using something other than floats. There’s nothing you can do to the float result to make it more exact — the error is already there.

You can ask sympy to evaluate a string as a symbolic expression by calling sympy.sympify:

import sympy

ans = sympy.sympify("(1 - 1/6) / (1/12 + 1/8)")

>>> print(ans, type(ans))
4 <class 'sympy.core.numbers.Integer'>

You can also use the fractions module from the standard library to do exact rational arithmetic:

from fractions import Fraction as F

a = F(1, 6)
b = F(1, 12)
c = F(1, 8)

ans = (1 - a) / (b + c)

>>> print(ans, type(ans))
4 <class 'fractions.Fraction'>

See also

What Every Computer Scientist Should Know About Floating-Point Arithmetic

5 Likes

thank you!
I think I like the sympy.sympify() option!

sympy.sympify("(1 - 1/6) / (1/12 + 1/8)")
>>> 4

Sympy is a very heavy and overkill dependency for this sort of task, and parsing a string for a mathematical expression is not very elegant. I would definitely take the fractions.Fraction approach by default.

1 Like