简体   繁体   中英

Parsing a double from a string which holds a value greater than Double.MaxValue

Consider the following java code:

String toParse = "1.7976931348623157E308"; //max value of a double in java        
double parsed = Double.parseDouble(toParse);
System.out.println(parsed);

For the mentioned value of 1.7976931348623157E308 everything makes sense and one gets the correct output.

Now, if one tries to parse 1.7976931348623158E308 (last digit before E incremented) you still get the maximum value printed into the console!
Only after trying to parse 1.7976931348623159E308 (again the last digit got incremented) and greater one gets Infinity .
Same behaviour for the corresponding negative values.

Why is ... 8E308 parsed to ... 7E308 and not Infinity ?

The SE 7 version of the parseDouble documentation refers to the valueOf documentation which says:

Note that the round-to-nearest rule also implies overflow and underflow behaviour; if the exact value of s is large enough in magnitude (greater than or equal to (MAX_VALUE + ulp(MAX_VALUE)/2), rounding to double will result in an infinity and if the exact value of s is small enough in magnitude (less than or equal to MIN_VALUE/2), rounding to float will result in a zero.

This is consistent with the statement that the rounding to type double is by the usual round-to-nearest rule of IEEE 754 floating-point arithmetic.

You have to imagine the conversion being done by first calculating the nearest floating point number ignoring the exponent limitation, and then checking whether the exponent fits. Double.MAX_VALUE is the closest number under that rule to some numbers that are strictly greater than it.

To confirm this is normal rounding behavior, consider the following program:

    public class Test {
      public static void main(String[] args) {
        double ulp = Math.ulp(Double.MAX_VALUE);
        System.out.println(ulp);
        System.out.println(Double.MAX_VALUE);
        System.out.println(Double.MAX_VALUE+ulp/2.0000000001);
        System.out.println(Double.MAX_VALUE+ulp/2);
      }
    }

It outputs:

1.9958403095347198E292
1.7976931348623157E308
1.7976931348623157E308
Infinity

Adding something even slightly less than half a ulp to Double.MAX_VALUE does not change it. Adding half a ulp overflows to infinity.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM