I'm experimenting with the precision of a double value in various programming languages.
#include <stdio.h>
int main() {
for (double i = 0.0; i < 3; i = i + 0.1) {
printf("%.17lf\n", i);
}
return 0;
}
#include <iostream>
using namespace std;
int main() {
cout.precision(17);
for (double i = 0.0; i < 3; i = i + 0.1) {
cout << fixed << i << endl;
}
return 0;
}
i = 0.0
while i < 3:
print(i)
i = i + 0.1
public class Main {
public static void main(String[] args) {
for (double i = 0.0; i < 3; i = i + 0.1) {
System.out.println(i);
}
}
}
0.00000000000000000
0.10000000000000001
0.20000000000000001
0.30000000000000004
0.40000000000000002
0.50000000000000000
0.59999999999999998
0.69999999999999996
0.79999999999999993
0.89999999999999991
0.99999999999999989
1.09999999999999990
1.20000000000000000
1.30000000000000000
1.40000000000000010
1.50000000000000020
1.60000000000000030
1.70000000000000040
1.80000000000000050
1.90000000000000060
2.00000000000000040
2.10000000000000050
2.20000000000000060
2.30000000000000070
2.40000000000000080
2.50000000000000090
2.60000000000000100
2.70000000000000110
2.80000000000000120
2.90000000000000120
0.00000000000000000
0.10000000000000001
0.20000000000000001
0.30000000000000004
0.40000000000000002
0.50000000000000000
0.59999999999999998
0.69999999999999996
0.79999999999999993
0.89999999999999991
0.99999999999999989
1.09999999999999987
1.19999999999999996
1.30000000000000004
1.40000000000000013
1.50000000000000022
1.60000000000000031
1.70000000000000040
1.80000000000000049
1.90000000000000058
2.00000000000000044
2.10000000000000053
2.20000000000000062
2.30000000000000071
2.40000000000000080
2.50000000000000089
2.60000000000000098
2.70000000000000107
2.80000000000000115
2.90000000000000124
0.0
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
1.0999999999999999
1.2
1.3
1.4000000000000001
1.5000000000000002
1.6000000000000003
1.7000000000000004
1.8000000000000005
1.9000000000000006
2.0000000000000004
2.1000000000000005
2.2000000000000006
2.3000000000000007
2.400000000000001
2.500000000000001
2.600000000000001
2.700000000000001
2.800000000000001
2.9000000000000012
0.0
0.1
0.2
0.30000000000000004
0.4
0.5
0.6
0.7
0.7999999999999999
0.8999999999999999
0.9999999999999999
1.0999999999999999
1.2
1.3
1.4000000000000001
1.5000000000000002
1.6000000000000003
1.7000000000000004
1.8000000000000005
1.9000000000000006
2.0000000000000004
2.1000000000000005
2.2000000000000006
2.3000000000000007
2.400000000000001
2.500000000000001
2.600000000000001
2.700000000000001
2.800000000000001
2.9000000000000012
I know that there are some errors in the double type itself about which we can learn more from blogs like Why You Should Never Use Float and Double for Monetary Calculations and What Every Computer Scientist Should Know About Floating-Point Arithmetic.
But these errors are not random! Every time the errors are the same, thus my question is why are these different for different programming languages?
Secondly, why are the precision errors in Java and Python same? [Java's JVM is written in C++ whereas the python interpreter is written in C]
But surprisingly their errors are same, but different from the errors in C and C++. Why is this happening?
The differences you're seeing are in how you print out the data, not in the data itself.
As I see it, we have two problems here. One is that you're not consistently specifying the same precision when you print out the data in each language.
The second is that you're printing the data out to 17 digits of precision, but at least as normally implemented (double being a 64-bit number with a 53-bit significand) a double really only has about 15 decimal digits of precision.
So, while (for example) C and C++ both require that your result be rounded "correctly", once you go beyond the limits of precision it's supposed to support, they can't guarantee much about producing truly identical results in every possible case.
But that's going to affect only how the result looks when you print it out, not how it's actually stored internally.
But these errors are not random!
Correct. That should be expected.
why are these different for different programming language?
Because you've formatted the output differently.
Why are the errors in Java and Python same?
They seem to have the same, or sufficiently similar default formatting.
I don't know about Python or Java but neither C and C++ insist that the printed decimal representation of a double value be as precise or concise as possible. So comparing printed decimal representations does not tell you everything about the actual value that is being printed. Two values could be the same in the binary representation but still legitimately print as different decimal strings in different languages (or different implementations of the same language).
Therefore your lists of printed values are not telling you that anything unusual is going on.
What you should do instead is print the exact binary representations of your double values.
Some useful reading. https://www.exploringbinary.com/