Problem on getting digits in a double variable

2019-05-04 00:24发布

问题:

I got a little problem with a function I need in my java progam. I want to check the total amount of digits, a 'double' variable has. (e.g.: 5 should return 1, 5.0034 should return 5, and 2.04 should return 3.) My function is this:

private int getDoubleLength (double a) {
        int len = 0;
        while (a != (int) a) {
            a *= 10;
        }
        while (a > 1) {
            len ++;
            a/=10;
        }
        System.out.println(String.format("Double %f has %d digits.",a,len));
        return len;
    }

Now this works perfectly, but when I am making some mathematical calculations, you get the slight errors of doubles: I divide 10 by cos(60), which is 0,5. The answer should be 20.0, but the program gives a 20.000000000000004 (that number, I copied it). My while loop gets stuck, and the program hangs.

Any ideas? (Or other great solutions for checking the digits of a number!)

回答1:

Doubles and floats and operations on then are not exact so there will always bee slight errors compared with algebraic calculations. If you are using cosines etc then you will always have to deal with these rounding errors which any book or web text on numerical analysis should describe. If you are using simple aritmetic operations look at java.lang.BigDecimal

For details on how floating point values are stored.see What Every Computer Scientist Should Know About Floating-Point Arithmetic



回答2:

toString().length() should solve it
remeber to substract the '.' if it is there and shouldn't be counted



回答3:

This is how I implemented mine, Simple converting to String when the double was to big returned String with an exponential representation. i.e 20000000 would return 2.0E+7, and the split would then split it from here resulting in wrong count. I used to BigDecimal and to toPlainString() method

protected int countDecimalDigits(Double d) {
    BigDecimal deci = BigDecimal.valueOf(d);
    int integerPlaces = 0;
    int decimalPlaces = 0;
    String text = deci.toPlainString();

    String[] integerDecimalSplit = text.split("\\.");
    if (null != integerDecimalSplit[0]) {
        integerPlaces = integerDecimalSplit[0].length();
    }
    if (integerDecimalSplit.length > 1) {
        decimalPlaces = integerDecimalSplit[1].length();
    }
    return integerPlaces + decimalPlaces;
}


回答4:

It's a rounding issue. I would use Strings, count the characters, and decide what figures are to be counted significant.