Pathological floating point problems: Difference between revisions
Content added Content deleted
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: | Line 1,529: | ||
we're exceeding the limits of our representation here, if we're using 64 bit IEEE-754 floating point arithmetic. |
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}}== |
=={{header|jq}}== |