If I execute
3*0.1, Julia prints the value as
0.30000000000000004. I believe the inaccuracy is caused by machine precision, but it doesn’t seem useful to me that Julia would display this. I also note that I have never encountered this kind of issue working with numbers greater than 1. What’s the cause of this issue, and what’s the best way around it?
If I execute
It is hard for Julia to know that you don’t want the result printed as accurately as possible. You can use the
round function if you want to show fewer digits of precision. There is also the PR https://github.com/JuliaLang/julia/pull/29249 to allow showing things in the REPL in a “compact” version which would end up being printed as:
julia> sprint(show, 0.1*3, context=:compact=>true) "0.3"
round does only work raliable in the windows built, see this thread
This was written in the context of “I only want to see a few digits and I don’t care about exact accuracy”.
I’d question the definition of exact accuracy - clearly, the exact solution is 0.3.
Also, 0.4 cannot be represented exactly, but
(0.1 + 0.1 + 0.1) + 0.1 produces
0.4. Not quite sure where the 4e-16 has gone, as I would have assumed numerical inaccuracies would compound.
Please read through PSA: floating-point arithmetic and see if you have further questions.
I find it weird that executing
0.3 but executing
3 * 0.1 prints
I understand how floating-point arithmetic works. The examples given there demonstrate catastrophic cancellation, and the result of all the calculations is equal to eps(). The article gives this example to demonstrate that all these calculations are performed in the same way. However, the examples which I am demonstrating can’t be replicated in other languages.
Eg. (in C, what I would expect)
printf("%1.16e\n", .3); 3.0000000000000004 printf("%1.16e\n", .1 + .1 + .1); 3.0000000000000004
Eg. (in Julia)
> .3 0.3 > .1 + .1 + .1 0.30000000000000004
Have you seen http://0.30000000000000004.com/?
That seems to print 2.9999999999999999e-01 (which Julia also does with
julia> using Printf julia> @printf "%1.16e\n" .3 2.9999999999999999e-01
Anyway, Julia uses the GRISU (or Ryu) algorithm to print the float. It guarantees that the generated strings can be parsed back to the original number while minimizing the number of digits.
julia> 2.9999999999999999e-01 0.3 julia> 0.3 0.3
0.3 is shorter here and thus preferable. But in the original example,
0.30000000000000004 are different floating point numbers and it would thus be an error to print
0.3 since it doesn’t parse back to the original number.
Are you sure? Cf
which is incorrect.
When working with 64-bit IEEE floats, all languages would perform these operations the same way, they may just print the results differently. Eg R would do
> z = 0.1 * 3 > z  0.3 > z - 0.3  5.551115e-17
Julia made the choice of printing floating values which are not equal differently. This is pretty much a given at this point and unlikely to change.
As for the workarounds, you can round the numbers before printing (
round), or just print rounded values using the standard library (
Printf.sprint & friends), or
or some other package (there are many), use decimal arithmetic
or the built-in rational type
Must have missed a compile, that put me off track >.<.
This is what I was missing. I’d suggest it would be useful to add this to the floating-point PSA referenced above.