There is a very well know issue of precision with floating-point variables and arithmetic in computers, know by computer scientist and engineers, it is related to how float numbers are represented in memory, 64 bits computer word (or 32, 16, 8 according the hardware). Instead of storing exact decimal numbers in memory, computers use an approximate binary representation (using zeros and ones), which can result in small rounding errors. This happens because some decimal numbers cannot be represented exactly in binary format, leading to cumulative discrepancies in complex mathematical calculations.
This diagram from Wikipedia illustrate how a floating number is represented in memory using 32 bits:https://en.wikipedia.org/wiki/Floating-point_arithmetic
The basic issues are:
◼
Limited representation of float numbers
◼
Comparison
◼
Propagation, accumulate errors
This precision issue is not a problem for most applications. But it is a big issue when you need precision in math, physics, engineering, banking and finance.
Fortunately Wolfram Language uses an arbitrary float representation and don’t have this issue.
In programming languages such as Python or Java there are big int and big float classes to handle that, but they are limited by the methods available at those classes, and they can compute those numbers freely with other classes and libraries.
In programming languages such as Python or Java there are big int and big float classes to handle that, but they are limited by the methods available at those classes, and they can compute those numbers freely with other classes and libraries.
First lest try some simple numerical computation in Wolfram Language and try it at other programming languages:
In[]:=
.1+.2
Out[]=
0.3
In[]:=
.1+.2==.3
Out[]=
True
Let’s test in other programming languages using interactive mode in a Linux PC (except for Fortran that is compiled):
In Python:
$ python
Python 3.11.5 (main, Sep 11 2023, 13:54:46) [GCC 11.2.0] on linux
Type “help”, “copyright”, “credits” or “license” for more information.
>>> .1 + .2
0.30000000000000004
>>> .1 + .2 == .3
False
Python 3.11.5 (main, Sep 11 2023, 13:54:46) [GCC 11.2.0] on linux
Type “help”, “copyright”, “credits” or “license” for more information.
>>> .1 + .2
0.30000000000000004
>>> .1 + .2 == .3
False
In Java:
$ jshell
| Welcome to JShell -- Version 11.0.9
| For an introduction type: /help intro
jshell> .1 + .2
$1 ==> 0.30000000000000004
jshell> .1 + .2 == .3
$2 ==> false
| Welcome to JShell -- Version 11.0.9
| For an introduction type: /help intro
jshell> .1 + .2
$1 ==> 0.30000000000000004
jshell> .1 + .2 == .3
$2 ==> false
In JavaScript:
$ node
Welcome to Node.js v16.18.0.
Type “.help” for more information.
> .1 + .2
0.30000000000000004
> .1 + .2 == .3
false
Welcome to Node.js v16.18.0.
Type “.help” for more information.
> .1 + .2
0.30000000000000004
> .1 + .2 == .3
false
In Lua, the math works, but the boolean comparison don’t:
$ lua
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> .1 + .2
0.3
> .1 + .2 == .3
false
Lua 5.4.3 Copyright (C) 1994-2021 Lua.org, PUC-Rio
> .1 + .2
0.3
> .1 + .2 == .3
false
In Julia:
$ julia
_
_
_ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type “?” for help, “]?” for Pkg help.
| | | | | | | / _`| |
| | |_| | | | (_| | | Version 1.10.2 (2024-03-01)
_/ |\__’_|_|_|\__’_| | Official https://julialang.org/ release
|__/ |
julia> .1 + .2
0.30000000000000004
julia> .1 + .2 == .3
false
_
_
_ _(_)_ | Documentation: https://docs.julialang.org
(_) | (_) (_) |
_ _ _| |_ __ _ | Type “?” for help, “]?” for Pkg help.
| | | | | | | / _`| |
| | |_| | | | (_| | | Version 1.10.2 (2024-03-01)
_/ |\__’_|_|_|\__’_| | Official https://julialang.org/ release
|__/ |
julia> .1 + .2
0.30000000000000004
julia> .1 + .2 == .3
false
In Fortran, the math does not work, but the boolean comparison works:
program sum_and_compare
implicit none
real :: a, b, c, sum
logical :: comparison
! Assign values
a = 0.1
b = 0.2
c = 0.3
! Calculate sum
sum = a + b
! Compare sum to 0.3
comparison = (sum == c)
! Print results
print *, “Sum of 0.1 and 0.2: “, sum
print *, “Is 0.1 + 0.2 equal to 0.3? “, comparison
end program sum_and_compare
Sum of 0.1 and 0.2: 0.300000012
Is 0.1 + 0.2 equal to 0.3? T
implicit none
real :: a, b, c, sum
logical :: comparison
! Assign values
a = 0.1
b = 0.2
c = 0.3
! Calculate sum
sum = a + b
! Compare sum to 0.3
comparison = (sum == c)
! Print results
print *, “Sum of 0.1 and 0.2: “, sum
print *, “Is 0.1 + 0.2 equal to 0.3? “, comparison
end program sum_and_compare
Sum of 0.1 and 0.2: 0.300000012
Is 0.1 + 0.2 equal to 0.3? T
In SQLite, it works:
$ sqlite
SQLite version 2.8.17
Enter “.help” for instructions
sqlite> select 0.1 + 0.2;
0.3
sqlite> select 0.1 + 0.2 == 0.3;
1
SQLite version 2.8.17
Enter “.help” for instructions
sqlite> select 0.1 + 0.2;
0.3
sqlite> select 0.1 + 0.2 == 0.3;
1
References:
The best discussion about this subject of computing float numbers I found are:
The best discussion about this subject of computing float numbers I found are:
◼
◼
Floating Point Arithmetic: Issues and Limitations
https://docs.python.org/3/tutorial/floatingpoint.html
https://docs.python.org/3/tutorial/floatingpoint.html
◼
How to | Control the Precision and Accuracy of Numerical Results
https://reference.wolfram.com/language/howto/ControlThePrecisionAndAccuracyOfNumericalResults.html
https://reference.wolfram.com/language/howto/ControlThePrecisionAndAccuracyOfNumericalResults.html
◼