Pathological floating point problems: Difference between revisions

Added Java implementation
m (→‎Siegfried Rump's example: made the (visible) expressions for the formula in the F function to appear closer to the task's version. .)
(Added Java implementation)
Line 1,529:
 
we're exceeding the limits of our representation here, if we're using 64 bit IEEE-754 floating point arithmetic.
 
=={{header|Java}}==
Uses BigRational class: [[Arithmetic/Rational/Java]]. For comparison purposes, each task is also implemented with standard 64-bit floating point numbers.
 
<lang java>import java.math.BigDecimal;
import java.math.RoundingMode;
 
public class FPProblems {
public static void wrongConvergence() {
int[] INDEXES = new int[] { 3, 4, 5, 6, 7, 8, 20, 30, 50, 100 };
// Standard 64-bit floating point
double[] fpValues = new double[100];
fpValues[0] = 2.0;
fpValues[1] = -4.0;
for (int i = 2; i < fpValues.length; i++) {
fpValues[i] = 111.0 - 1130.0 / fpValues[i - 1] + 3000.0 / (fpValues[i - 1] * fpValues[i - 2]);
}
// Using rational representation
BigRational[] brValues = new BigRational[100];
brValues[0] = BigRational.valueOf(2);
brValues[1] = BigRational.valueOf(-4);
for (int i = 2; i < brValues.length; i++) {
// Using intermediate values for better readability
BigRational clause2 = BigRational.valueOf(1130).divide(brValues[i - 1]);
BigRational clause3 = BigRational.valueOf(3000).divide(brValues[i - 1].multiply(brValues[i - 2]));
brValues[i] = BigRational.valueOf(111).subtract(clause2).add(clause3);
}
System.out.println("Wrong Convergence Sequence");
for (int n : INDEXES) {
BigDecimal value = brValues[n - 1].toBigDecimal(16, RoundingMode.HALF_UP);
System.out.println(" For index " + n + ", FP value is " + fpValues[n - 1] + ", and rounded BigRational value is " + value.toPlainString());
}
return;
}
public static void chaoticBankSociety() {
System.out.println("Chaotic Bank Society");
double balance = Math.E - 1.0;
// Calculate e using first 1000 terms of the reciprocal of factorials formula
BigRational e = BigRational.ONE;
BigRational d = BigRational.ONE;
for (int i = 1; i < 1000; i++) {
d = d.multiply(BigRational.valueOf(i));
e = e.add(d.reciprocal());
}
System.out.println("DEBUG: e=" + e.toBigDecimal(100, RoundingMode.HALF_UP).toPlainString());
// Alternatively,
// BigRational e = BigRational.valueOf(Math.E);
BigRational brBalance = e.subtract(BigRational.ONE);
for (int year = 1; year <= 25; year++) {
balance = (balance * year) - 1.0;
brBalance = brBalance.multiply(BigRational.valueOf(year)).subtract(BigRational.ONE);
BigDecimal bdValue = brBalance.toBigDecimal(16, RoundingMode.HALF_UP);
System.out.println(" Year=" + year + ", FP balance=" + balance + ", BigRational balance=" + bdValue.toPlainString());
}
}
public static void siegfriedRump() {
System.out.println("Siegfried Rump formula");
double fpValue;
{
double a = 77617.0;
double b = 33096.0;
fpValue = 333.75 * Math.pow(b, 6) + a * a * (11.0 * a * a * b * b - Math.pow(b, 6) - 121.0 * Math.pow(b, 4) - 2.0) + 5.5 * Math.pow(b, 8) + a / (2.0 * b);
}
BigRational brValue;
{
BigRational a = BigRational.valueOf(77617);
BigRational b = BigRational.valueOf(33096);
BigRational clause1 = BigRational.valueOf(333.75).multiply(b.pow(6));
BigRational clause2a = BigRational.valueOf(11).multiply(a).multiply(a).multiply(b).multiply(b);
BigRational clause2b = b.pow(6).add(BigRational.valueOf(121).multiply(b.pow(4))).add(BigRational.valueOf(2));
BigRational clause2 = a.multiply(a).multiply(clause2a.subtract(clause2b));
BigRational clause3 = BigRational.valueOf(5.5).multiply(b.pow(8));
BigRational clause4 = a.divide(b.multiply(BigRational.valueOf(2)));
brValue = clause1.add(clause2).add(clause3).add(clause4);
}
System.out.println(" FP value is " + fpValue);
System.out.println(" BigRational rounded value is " + brValue.toBigDecimal(64, RoundingMode.HALF_UP).toPlainString());
System.out.println(" BigRational full value is " + brValue.toString());
}
public static void main(String... args) {
wrongConvergence();
System.out.println();
chaoticBankSociety();
 
System.out.println();
siegfriedRump();
}
}</lang>
{{out}}
<pre>Wrong Convergence Sequence
For index 3, FP value is 18.5, and rounded BigRational value is 18.50000000000000
For index 4, FP value is 9.378378378378379, and rounded BigRational value is 9.378378378378378
For index 5, FP value is 7.801152737752169, and rounded BigRational value is 7.801152737752161
For index 6, FP value is 7.154414480975333, and rounded BigRational value is 7.154414480975249
For index 7, FP value is 6.806784736924811, and rounded BigRational value is 6.806784736923633
For index 8, FP value is 6.592632768721792, and rounded BigRational value is 6.592632768704438
For index 20, FP value is 98.34950312216536, and rounded BigRational value is 6.043552110189269
For index 30, FP value is 99.99999999999893, and rounded BigRational value is 6.006786093031206
For index 50, FP value is 100.0, and rounded BigRational value is 6.000175846627187
For index 100, FP value is 100.0, and rounded BigRational value is 6.000000019319478
 
Chaotic Bank Society
DEBUG: e=2.718281828459045235360287471352662497757247093699959574966967627724076630353547594571382178525166427
Year=1, FP balance=0.7182818284590451, BigRational balance=0.7182818284590452
Year=2, FP balance=0.4365636569180902, BigRational balance=0.4365636569180905
Year=3, FP balance=0.30969097075427054, BigRational balance=0.3096909707542714
Year=4, FP balance=0.23876388301708218, BigRational balance=0.2387638830170857
Year=5, FP balance=0.1938194150854109, BigRational balance=0.1938194150854282
Year=6, FP balance=0.16291649051246537, BigRational balance=0.1629164905125695
Year=7, FP balance=0.1404154335872576, BigRational balance=0.1404154335879862
Year=8, FP balance=0.12332346869806088, BigRational balance=0.1233234687038897
Year=9, FP balance=0.1099112182825479, BigRational balance=0.1099112183350075
Year=10, FP balance=0.09911218282547907, BigRational balance=0.09911218335007541
Year=11, FP balance=0.09023401108026974, BigRational balance=0.09023401685082952
Year=12, FP balance=0.08280813296323686, BigRational balance=0.08280820220995428
Year=13, FP balance=0.07650572852207915, BigRational balance=0.07650662872940558
Year=14, FP balance=0.07108019930910814, BigRational balance=0.07109280221167809
Year=15, FP balance=0.06620298963662208, BigRational balance=0.06639203317517140
Year=16, FP balance=0.05924783418595325, BigRational balance=0.06227253080274239
Year=17, FP balance=0.007213181161205284, BigRational balance=0.05863302364662064
Year=18, FP balance=-0.8701627390983049, BigRational balance=0.05539442563917152
Year=19, FP balance=-17.533092042867793, BigRational balance=0.05249408714425881
Year=20, FP balance=-351.66184085735586, BigRational balance=0.04988174288517625
Year=21, FP balance=-7385.898658004473, BigRational balance=0.04751660058870116
Year=22, FP balance=-162490.7704760984, BigRational balance=0.04536521295142560
Year=23, FP balance=-3737288.7209502636, BigRational balance=0.04339989788278872
Year=24, FP balance=-8.969493030280632E7, BigRational balance=0.04159754918692921
Year=25, FP balance=-2.242373258570158E9, BigRational balance=0.03993872967323021
 
Siegfried Rump formula
FP value is -1.1805916207174113E21
BigRational rounded value is -0.8273960599468213681411650954798162919990331157843848199178148417
BigRational full value is -54767/66192</pre>
 
=={{header|jq}}==