Hacker News new | ask | show | jobs
by Tainnor 1811 days ago
No, exact precision arithmetic can do that 16/31 example without loss of precision:

  from fractions import Fraction
  
  # salary is $3210.55
  salary = Fraction(321055,100)
  monthlyRate = Fraction(16,31)

  print(salary*monthlyRate)
This will give you an exact result. Now, at some point you'll have to round to the nearest cent (or whatever), true. However, you don't have to round between individual calculations, hence rounding errors cannot accumulate and propagate.

The propagation of errors is the main challenge with floating point numbers (regardless of which base you use). The theory is well understood (in the sense that we can analyse an algorithm and predict upper bounds on the relative error), but not necessarily intuitive and easy to get wrong.

Decimal floating-point circumvents the issue by just not introducing errors at all: money can be represented exactly with decimal floating point (barring very exotic currencies), therefore errors also can't propagate. Exact arithmetic takes the other approach where computations are exact no matter what (but this comes at other costs, e.g. speed and the inability to use transcendental functions such as exp).

For binary floating point, that doesn't work. It introduces errors immediately since it can't represent money well and these errors may propagate easily.

1 comments

Of course, if you use "fractions" then, we agree, no error will be introduced nor accumulated over computations which is better. The code base I'm talking about is Java 10 years ago. I was not aware of fractions at that time. There was only BigDecimal which was painful to work with (the reason why we ditched it at the time).
It's mostly painful because Java doesn't allow custom types to use operators, which I think was a maybe reasonable principle applied way too strictly. The same applies to any Fraction type you'd implement in Java.

Still, I'll take "verbose" over "error-prone and possibly wrong".