Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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?

like image 320
KeyNone Avatar asked Nov 24 '12 02:11

KeyNone


People also ask

What does double parse double do?

Double parseDouble() method in Java with examples The parseDouble() method of Java Double class is a built in method in Java that returns a new double initialized to the value represented by the specified String, as done by the valueOf method of class Double.

What is the value of double Max_value?

Double. MAX_VALUE is the maximum value a double can represent (somewhere around 1.7*10^308).

What is double Positive_infinity?

public static final double POSITIVE_INFINITY. A constant holding the positive infinity of type double . It is equal to the value returned by Double.


1 Answers

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.

like image 71
Patricia Shanahan Avatar answered Sep 28 '22 14:09

Patricia Shanahan