Code: My original large code had such a problem, so I broke it down into the below smallest code sample:
public class test {
static double precision = 2;
public static void main(String[] args) {
for (; precision < 100; precision++) {
int PI = (int) Math.round(Math.PI * precision);
double x1 = makePrecise(Math.PI / 2), x2 = makePrecise(PI / precision - Math.PI / 2);
if (x1 == x2)
System.out.println(precision + "\t" + x1 + "\t" + PI / precision + "\t" + (x1 + x2));
else
System.out.println(precision + "\t" + x1 + "\t" + x2 + "\t" + PI / precision + "\t" + (x1 + x2));
}
}
static double makePrecise(double num) {
return Math.round(num * precision) / precision;
}
}
My problem:
I do not understand why x1 == x2
only at some specific values of precision
. Either they should be equal at all values of precision
, or the values at which they are equal should follow a trend. Unfortunately, as you can see below, there is really no trend here. At lower values of precision
, it's like +3/+2/+2/+3/+2/+2/...
but at higher precision
values it's like +1/+2/+2/+2/+1/+2/+2/+2/+1...
. I do not exactly understand the underlying working here.
Please explain exactly why such a output is generated, especially since there doesn't seem to be any trend in it.
Output for x1==x2
: (for reference)
2.0 1.5 3.0 3.0
5.0 1.6 3.2 3.2
7.0 1.5714285714285714 3.142857142857143 3.142857142857143
9.0 1.5555555555555556 3.111111111111111 3.111111111111111
12.0 1.5833333333333333 3.1666666666666665 3.1666666666666665
14.0 1.5714285714285714 3.142857142857143 3.142857142857143
16.0 1.5625 3.125 3.125
19.0 1.5789473684210527 3.1578947368421053 3.1578947368421053
21.0 1.5714285714285714 3.142857142857143 3.142857142857143
[rows deleted to avoid bloat]
79.0 1.5696202531645569 3.1392405063291138 3.1392405063291138
81.0 1.5679012345679013 3.1358024691358026 3.1358024691358026
82.0 1.5731707317073171 3.1463414634146343 3.1463414634146343
84.0 1.5714285714285714 3.142857142857143 3.142857142857143
86.0 1.569767441860465 3.13953488372093 3.13953488372093
88.0 1.5681818181818181 3.1363636363636362 3.1363636363636362
89.0 1.5730337078651686 3.146067415730337 3.146067415730337
91.0 1.5714285714285714 3.142857142857143 3.142857142857143
93.0 1.5698924731182795 3.139784946236559 3.139784946236559
95.0 1.568421052631579 3.136842105263158 3.136842105263158
96.0 1.5729166666666667 3.1458333333333335 3.1458333333333335
98.0 1.5714285714285714 3.142857142857143 3.142857142857143
Output for x1 != x2
3.0 1.6666666666666667 1.3333333333333333 3.0 3.0
4.0 1.5 1.75 3.25 3.25
6.0 1.5 1.6666666666666667 3.1666666666666665 3.166666666666667
8.0 1.625 1.5 3.125 3.125
10.0 1.6 1.5 3.1 3.1
11.0 1.5454545454545454 1.6363636363636365 3.1818181818181817 3.1818181818181817
13.0 1.5384615384615385 1.6153846153846154 3.1538461538461537 3.153846153846154
15.0 1.6 1.5333333333333334 3.1333333333333333 3.1333333333333337
17.0 1.588235294117647 1.5294117647058822 3.1176470588235294 3.117647058823529
18.0 1.5555555555555556 1.6111111111111112 3.1666666666666665 3.166666666666667
20.0 1.55 1.6 3.15 3.1500000000000004
22.0 1.5909090909090908 1.5454545454545454 3.1363636363636362 3.1363636363636362
[rows deleted to avoid bloat]
78.0 1.5769230769230769 1.564102564102564 3.141025641025641 3.141025641025641
80.0 1.575 1.5625 3.1375 3.1375
83.0 1.5662650602409638 1.5783132530120483 3.144578313253012 3.144578313253012
85.0 1.576470588235294 1.5647058823529412 3.1411764705882352 3.1411764705882352
87.0 1.5747126436781609 1.5632183908045978 3.1379310344827585 3.137931034482759
90.0 1.5666666666666667 1.5777777777777777 3.1444444444444444 3.1444444444444444
92.0 1.576086956521739 1.565217391304348 3.141304347826087 3.141304347826087
94.0 1.574468085106383 1.5638297872340425 3.1382978723404253 3.1382978723404253
97.0 1.5670103092783505 1.577319587628866 3.1443298969072164 3.1443298969072164
99.0 1.5757575757575757 1.5656565656565657 3.1414141414141414 3.1414141414141414
PS: As you can see in both the outputs, x1+x2==PI
always. So, the only floating-point arithmetic that I ever did in this code ((PI / precision - Math.PI / 2)
) is indeed not broken. Hence, my question is not a duplicate of Is floating point math broken?