Instantly share code, notes, and snippets.

# hillmanli-seekers/TestDouble.java Last active Sep 14, 2018

BigDecimal vs double: illustration of accuracy and performance impact
 import java.math.BigDecimal; import java.util.function.Consumer; import java.util.function.DoubleSupplier; import java.util.stream.DoubleStream; public class TestDouble { private static double doubleTotal = 0; private static double kahanDoubleTotal = 0; private static BigDecimal bdTotal = BigDecimal.ZERO; public static void main(String[] args) { int iteration = 100000; double[] values = construct(Math::random, iteration); System.out.printf("Time taken for double calculation: %fms%n", time(TestDouble::sumToDouble, values)); System.out.printf("Time taken for Kahan double calculation: %fms%n", time(TestDouble::kahanSumToDouble, values)); System.out.printf("Time taken for BigDecimal calculation: %fms%n", time(TestDouble::sumToBigDecimal, values)); System.out.printf("Value diff for simple sum: %s%n", bdTotal.subtract(BigDecimal.valueOf(doubleTotal)).abs().toString()); System.out.printf("Value diff for Kahan sum: %s%n", bdTotal.subtract(BigDecimal.valueOf(kahanDoubleTotal)).abs().toString()); } private static double time(Consumer consumer, double[] values) { long start = System.nanoTime(); consumer.accept(values); long end = System.nanoTime(); return 1.0 * (end - start) / (1000 * 1000); } private static double[] construct(DoubleSupplier supplier, int size) { return DoubleStream .iterate(supplier.getAsDouble(), operand -> supplier.getAsDouble()) .limit(size) .toArray(); } private static void kahanSumToDouble(double[] values) { double approxError = 0; for (double value : values) { double adjustedValue = value - approxError; double adjustedSum = kahanDoubleTotal + adjustedValue; approxError = (adjustedSum - kahanDoubleTotal) - adjustedValue; kahanDoubleTotal = adjustedSum; } } private static void sumToDouble(double[] values) { for (double value : values) { doubleTotal += value; } } private static void sumToBigDecimal(double[] values) { BigDecimal ret = BigDecimal.ZERO; for (double value : values) { ret = ret.add(BigDecimal.valueOf(value)); } bdTotal = ret; } }
Owner Author

### hillmanli-seekers commented Mar 30, 2017 • edited

 A sample run will produce following result. Time taken for double calculation: 1.716163ms Time taken for Kahan double calculation: 3.549576ms Time taken for BigDecimal calculation: 97.298124ms Value diff for simple sum: 8.68145523891E-10 Value diff for Kahan sum: 1.854476109E-12