Reputation: 81
I was using the Math.pow() method, and the results I get differ from the result I got from a calculator.
The code I used:
public static int getSum(int a, int b, int c, int d){
return (int)(d*Math.pow(16.0,6.0)+c*Math.pow(16.0,4.0)+b*Math.pow(16.0,2.0)+a);
}
Printing
getSum(0,0,128,191)
prints out 2147483647 while google calculator shows 3212836864.
What causes this?
Upvotes: 1
Views: 2341
Reputation: 14255
Just to add an explanation to the existing answers (if e.g. someone wonders why there is no integer overflow):
The spec says under 5.1.3. Narrowing Primitive Conversion
In the first step, the floating-point number is converted either to a long, if T is long, or to an int, if T is byte, short, char, or int, as follows:
If the floating-point number is NaN (§4.2.3), the result of the first step of the conversion is an int or long 0.
Otherwise, if the floating-point number is not an infinity, the floating-point value is rounded to an integer value V, rounding
toward zero using IEEE 754 round-toward-zero mode (§4.2.3). Then
there are two cases:
If T is long, and this integer value can be represented as a long, then the result of the first step is the long value V.
Otherwise, if this integer value can be represented as an int, then the result of the first step is the int value V.
Otherwise, one of the following two cases must be true:
The value must be too small (a negative value of large magnitude or negative infinity), and the result of the first step is the smallest representable value of type int or long.
The value must be too large (a positive value of large magnitude or positive infinity), and the result of the first step is the largest representable value of type int or long.
So your double
value returned from Math.pow
is converted to the largest representable int
(i.e. Integer.MAX_VALUE
).
Note that this part is specific to floating-point number conversions. If your method was e.g. defined as (note the additional cast to long
)
public static int getSum(int a, int b, int c, int d){
// Casting twice doesn't make sense. It's just here for demonstration.
return (int)(long)(d*Math.pow(16.0,6.0)+c*Math.pow(16.0,4.0)+b*Math.pow(16.0,2.0)+a);
}
The corresponding part in spec would be
A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.
And your method would return -1082130422 (aka integer overflow).
Upvotes: 6
Reputation: 2451
change your code to following: int --> 32 bit (2^32 -1) Easy way to test max length is System.out.println(Integer.MAX_VALUE); ==> 2147483647
public static Long getSum(int a, int b, int c, int d) {
return (long) (d * Math.pow(16.0, 6.0) + c * Math.pow(16.0, 4.0) + b * Math.pow(16.0, 2.0) + a);
}
Upvotes: 0
Reputation: 559
Java int
has capability of store 2^32
, which if it is signed, half is used by negative numbers. For positive numbers, can store up to 2^31 -1 = 2147483647
. You need a bigger type for this task, use long
and it can store up to 9 223 372 036 854 775 807
when it is signed.
Upvotes: 4
Reputation: 2799
The maximum value of an integer in java is 2,147,483,647. You should keep it a double value and Math.ceil()
or Math.floor()
. You can also cast it into a long value because that is a 64 bit two's compliment integer.
Upvotes: 0
Reputation: 224
2,147,483,647 is the max value an int can hold. If you need larger numbers, like in this case, make your function return a long instead.
Upvotes: 3