Skip to content

Instantly share code, notes, and snippets.

/Inexact.java Secret

Created June 21, 2017 09:26
Show Gist options
  • Save anonymous/eabdabea96b7378372f8ff1594811eca to your computer and use it in GitHub Desktop.
Save anonymous/eabdabea96b7378372f8ff1594811eca to your computer and use it in GitHub Desktop.
Shows inexact calculation issues with double
package scrap.stackoverflow;
import java.math.BigDecimal;
import java.math.RoundingMode;
public class Inexact {
static double roundToTwoPlacesA(double n) {
final double m = Math.rint(100 * n);
return m / 100.0;
}
static double roundToTwoPlacesB(double n) {
final long m = Math.round(10000000.0 * n);
final double x = 0.00001 * m;
final long r = (long) Math.rint(x);
return r / 100.0;
}
static double roundToTwoPlacesC(double n) {
return BigDecimal.valueOf(n).setScale(2, RoundingMode.HALF_EVEN).doubleValue();
}
private static void checkMath(BigDecimal amountB, BigDecimal taxB) {
double amountD = amountB.doubleValue();
double taxD = taxB.doubleValue();
BigDecimal rawB = amountB.multiply(taxB);
BigDecimal resultB = rawB.setScale(2, RoundingMode.HALF_EVEN);
double resultD = roundToTwoPlacesB(amountD * taxD);
String strB = resultB.toString();
String strD = BigDecimal.valueOf(resultD).setScale(2).toString();
if (!strB.equals(strD)) {
System.out.println("Failed for " + amountB + " * " + taxB + " = " + strB + " vs " + strD);
System.out.println("Raw result : " + rawB + ", Double.toString(): " + Double.toString(resultD));
}
}
public static void main(String[] args) {
for (int rateInt = 1; rateInt < 1000; rateInt++) {
BigDecimal rate = BigDecimal.ONE.setScale(20).divide(BigDecimal.valueOf(rateInt), RoundingMode.HALF_EVEN);
for (int cents = 123456; cents < 123456 + 100000; cents++) {
BigDecimal amount = new BigDecimal(cents).scaleByPowerOfTen(-2);
checkMath(amount, rate);
}
}
System.out.println("Nothing found...");
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment