mardi 11 octobre 2016

How to unit test numerical computation for "no precision error"?

We have a large system written in Java where precision, for most of the time, is not that important. We therefore store all numbers in double.

However, several years later new requirement emerged and for certain rare scenarios precision matters a great deal. So I am having this situation where I need to take a price (represented in double), a base (also represented in double), and round the price to the nearest multiple of that base, and store the result, again, in double.

In decimal form this is trivial:result = roundDownToBase(price + base*0.5, base)

I understand that carrying out the above formula naively with double will result in precision issue. I also understand a proper fix is to convert everything into BigDecimal during the calculation.

My question is, how can I systematically (unit) test that the BigDecimal version does not have the same precision issue that double version has? I can randomly choose a few values and assert the results, but that does not seem to give me too much confidence given the universe of inputs is infinite. Or, is there a way to systematically pick a few representative values in unit tests, and yield a reasonably high confidence of the code quality?

P.S. my code:

    public static double roundToNear(double price, double base) {
        BigDecimal value = BigDecimal.valueOf(price);
        BigDecimal baseValue = BigDecimal.valueOf(base);
        BigDecimal two = BigDecimal.valueOf(2);
        BigDecimal halfUp = value.add(baseValue.divide(two));
        return roundDownToBase(halfUp.doubleValue(), base);
    }

    public static double roundDownToBase(double value, double base) {
        BigDecimal val1 = BigDecimal.valueOf(value);
        BigDecimal val2 = BigDecimal.valueOf(base);
        BigDecimal remainder = val1.remainder(val2);
        return MathUtil.isZeroOrNaN(remainder.doubleValue()) ? value:val1.subtract(remainder).doubleValue();
    }

Aucun commentaire:

Enregistrer un commentaire