Java math wierdness



  • Can someone explain the results from this tiny Java program? I can explain the first line of output, but have no clue about the second line. I thought about posting the results, but thought it might be more fun to let people guess. Is there anyone here who doesn't have access to Java?

     

      public static void main(String[] args) {
            long maxPlusOne = Long.MAX_VALUE + 1;
            System.out.printf("MAX_VALUE+1=%d\nround(MAX_VALUE+1)=%d\n",
                    maxPlusOne,
                    Math.round(maxPlusOne));
        }

     P.S.
    I don't know why the board drops the closing square bracket in String[] args. You will need to put it back before compiling.



  • I don't, so I tried it in .NET but it doesn't even compile.

            long maxPlusOne = long.MaxValue + 1;
    

    results in a compile error: The operation overflows at compile time in checked mode



  •  Math.round() expects a double or a float as an argument.

     You are passing a long, so it gets automagically casted.



  •  @lupo said:

     Math.round() expects a double or a float as an argument.

     You are passing a long, so it gets automagically casted.

    Then you would expect the same results when passing the same values to your own method...

    public static void printLongAsDouble(double d) {

     System.out.println(d);

    }

    You would be wrong.



  • Java seems to prefer the cast to float instead of double:

    	public static void main(String[] args) {
    long maxPlusOne = Long.MAX_VALUE + 1;
    printRound(maxPlusOne);
    }

    static void printRound(double d) {
    System.out.println(Math.round(d));
    }
    static void printRound(float f) {
    System.out.println(Math.round(f));
    }
    Output is -2147483648

    But still a WTF, since long to double would be a better choice that long to float ;)


  • It's weird how weird is spelled 'weird'.



  • Please try it again without the Math.round() in your own methods. You haven't properly isolated the cast.

    Besides, casting a long as a float should only lose precision, not value, in any language.

     



  • @Rick said:

    Can someone explain the results from this tiny Java program? I can explain the first line of output, but have no clue about the second line. I thought about posting the results, but thought it might be more fun to let people guess. Is there anyone here who doesn't have access to Java?

    I'm too lazy to guess, so here's the result I got:

    MAX_VALUE+1=-9223372036854775808
    round(MAX_VALUE+1)=-2147483648

    As for why... Math.round has two overloads, long round(double a) and int round(float a). Both of them are applicable when the argument is a long, but the latter is chosen, because float is considered a subtype of double, and thus the second method is more specific. Since it returns the closest int to the argument, the best it can do is to return -232.

    @Rick said:

    P.S.
    I don't know why the board drops the closing square bracket in String[ args. You will need to put it back before compiling.

    []] is BBcode for [].



  • @pinkduck said:

    It's weird how weird is spelled 'weird'.
     

    Yes, it looked wierd when I wrote it.

     



  • @Spectre said:

    [ Since it returns the closest int to the argument, the best it can do is to return -232.

     

    Ahh. Got it. Math.round(float f) returns Integer.MIN_VALUE for anything less than Integer.MIN_VALUE. ouch.

    At least I can see the logic now. 

    But, in my opinion, the best it could do would be to throw an exception.



  • Yeah, what they said.

    More practically, if you are expecting to use big numbers rather than the usual safe range that can be represented by 64 bits, try out a BigInteger.   Math.round() isn't defined for integer types because, of couse, why would anyone need to round an integer?





  • Max+1 is Min, in 2's complement. And it appears that the conversion is working. Its just that long is 64 bit,

    -9223372036854775808 to +9223372036854775807.

    round(), however, is forcing the conversion of that to 32 bit first. This clips the values to the range

    -2147583648 to 2147583647

    which is then rounded, and displayed.

    The real WTF is why the long to int didn't throw an exception.



  • @ratboy667 said:

    Max+1 is Min, in 2's complement. And it appears that the conversion is working. Its just that long is 64 bit,

    -9223372036854775808 to +9223372036854775807.

    round(), however, is forcing the conversion of that to 32 bit first. This clips the values to the range

    -2147583648 to 2147583647

    which is then rounded, and displayed.

    The real WTF is why the long to int didn't throw an exception.

     

    Actually, Long.MIN_VALUE is cast to float, not to int.

    The weirdness is that it isn't cast to double for the round.



  • @ratboy667 said:

    Max+1 is Min, in 2's complement. And it appears that the conversion is working. Its just that long is 64 bit,

    -9223372036854775808 to +9223372036854775807.

    round(), however, is forcing the conversion of that to 32 bit [b]afterward[/b]. This clips the [b]rounded[/b] values to the range

    -2147583648 to 2147583647

    which is then displayed.

    The real WTF is why the long to int didn't throw an exception.



  • You guys should try Java2k, an esoteric programming language. Methods that return primitive types have a 10% chance of returning a random value instead of executing normally and it uses a 11-based number system.

    http://www.p-nand-q.com/humor/programming_languages/java2k.html


  • Discourse touched me in a no-no place

    [quote user="Renan "C#" Sousa"]http://www.p-nand-q.com/humor/programming_languages/java2k.html[/quote] Looks rather like Java's (simple) equivilant of C's DS9K.



  • @PJH said:

    [quote user="Renan "C#" Sousa"]http://www.p-nand-q.com/humor/programming_languages/java2k.html
    Looks rather like Java's (simple) equivilant of C's DS9K.[/quote]

    [url=http://www.undefined.net/1/0/?strip=12]Only it's completely different and with more suffering.[/url] A DeathStation implements the language perfectly, but acts unusually and unexpectedly on any implementation-defined or undefined constructs. That one is just an esoteric language, not a Java implementation.

    Amusingly, a DeathStation for Java would not be very interesting, since it leaves very little leeway to the implementation.



  • @Rick said:

    Besides, casting a long as a float should only lose precision, not value, in any language.

     

    For at least some specific cases, such as max values, any loss of precision will necessarily result in a loss of value.


Log in to reply