I'm trying to convert a function in java to pl/pgsql, and one problem that I found is when I'm trying to sum 2 negative numbers, and a get a positive number, more specifically :
public void sum(){
int n1 = -1808642602;
int n2 = -904321301;
System.out.println(n1 + n2);// result is 1582003393
}
And in pl/pgsql I get an integer out of range error, and if I change the variables type to bigint i get a normal sum of 2 negative numbers, that is -2712963903, instead of 1582003393
How do I do to pl/pgsql get the same result without printing an integer out of range error?
This happens because the Java int underflows and doesn't tell you.
To get the answer you are looking for in pl, you need to use bigint. Then detect the case when the result is less than Java Integer.MIN_INT (-2^31), which is the case where Java will give a positive result. To get what Java would give you, add 2^32.
You are overflowing the int try the same thing with long and it should work.
It's overflowing, because the result is too big for an int. Use long instead.
Java sums them as 32 bit signed integers, which wrap at -231. Have you tried a 64 bit long instead?
That valid rand of int in Java is -2,147,483,648 to 2,147,483,647 (-2^31 - 2^31-1).
You are causing an Integer underflow. You should use a type long instead of int which ranges from -2^63 to 2^63-1
Java treats those 2 numbers as signed integers.
Basically the scope for singed integers is -2,147,483,648 to 2,147,483,647 (-2^31 - 2^31-1).
Hence the sum of those to values is -2712963903 which is less than the the minimum -2^31 so underflows and then wraps around by doing 2^32 - 2712963903 which gives you the signed int 1582003393.
Try using a long which will not overflow in this case (but will for large enough numbers)
System.out.println((long) n1 + n2);
Related
Lets consider below lines of code.
1- int ExA = Integer.parseInt("123");
2- int ExB = Integer.parseInt("2147483660");
if we execute line 1 than variable ExA will be successfully populated by 123
but if we execute line 2 than we will "NumberFormatException" because in line 2 number provided to the 'parseInt' function is beyond int range.
I am looking for a solution where I can get overflowed int value if we have a number in string format whose value is beyond int range. Please help me figuring out.
You can use BigInteger instead.
BigInteger ExB = new BigInteger("2147483660");
Regarding JDK docs,
BigInteger must support values in the range -2^Integer.MAX_VALUE
(exclusive) to +2^Integer.MAX_VALUE (exclusive) and may support values
outside of that range. The range of probable prime values is limited
and may be less than the full supported positive range of BigInteger.
The range must be at least 1 to 2^500000000
BigInteger is sometimes messy to implement. You could have a long, and just do Long.parseLong("2147483660"), if it doesn't exceed 2^64.
My question: how to make -2147483648 a positive number in Java?
My thoughts:
There are many ways to make a negative number positive:
Make a negative number positive
however, for the edge case, where the min value of a int in Java is -2147483648, all those methods do not work.
What should I do? Thank you very much!
If you care about it staying an int: you can't. The int primitive fits only values from -2147483648 up to and including 2147483647.
However, if you just want to turn -2147483648 into the integer number 2147483648, then use a long:
public class Test
{
public static void main(String[] args)
{
int v = -2147483648;
long r = -(long)v;
System.out.print(r);
}
}
And done: 2147483648.
Of course, also read through https://docs.oracle.com/javase/tutorial/java/nutsandbolts/datatypes.html to get familiar with the limitations of all the primitive data types. And if that still isn't enough and you need arbitrary length integers, BigInteger is available.
My question: how to make -2147483648 a positive number in Java?
There is no value that is representable as an int that is equal to +2147483648.
So the idea of "making -2147483648 positive" as an int has no meaning. You simply cannot do it1.
But you could represent +2147483648 as a long or as a BigInteger (or a few other ways with various caveats.)
What should I do?
Use long (though that has the same issue with Long.MIN_VALUE) or BigInteger or BigDecimal or some other representation.
Or just treat this as a "feature" rather than a problem ... and work around it. For example, remove the sign after you have put it into the StringBuilder or treat -2147483648 as a special case.
1 - It is a mathematical fact that 2's complement signed representations are not symmetric about zero. There is one more negative number ( < 0) than positive ( > 0), and therefore one negative number doesn't have a corresponding positive number.
I was trying to check different inputs and creating infinite loops in java and I found that once the int is getting incremented over the maximum limit it turns in to negative -2147482958. I am just increasing the int in infinite loop...
Code:
public static void infiniteLoop(){
for(int i=0;i>-1;i++){
i = i + 1000;
System.out.println(i);
}
}
The last to value gets printed out is,
2147483337
-2147482958
Now, Why does it goes to negative?
Why does it goes to negative?
Because that is what is specified to happen in Java when an int calculation overflows.
JLS 15.18.2
"If an integer addition overflows, then the result is the low-order bits of the mathematical sum as represented in some sufficiently large two's-complement format. If overflow occurs, then the sign of the result is not the same as the sign of the mathematical sum of the two operand values."
(This doesn't explicitly say that overflow always gives a negative number. And it doesn't always. But if you apply the rule, it does explain why incrementing Integer.MAX_VALUE by +1 gives you Integer.MIN_VALUE ...)
According to the documentation:
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 (0x80000000) and a maximum value of 2,147,483,647 (0x7FFFFFFF) (inclusive)
So when you add one to an integer's max value:
0x7FFFFFFF + 0x00000001 = 0x80000000 (-2,147,483,648)
Because when the value of an int reaches Integer.MAX_VALUE, incrementing it causes overflow and hence wraps around to Integer.MIN_VALUE.
To use larger integers, use a long instead which has 64 bits.
Because int ranges from -2,147,483,648 to 2,147,483,647. Hence,once it reaches it upper limit, it overflows and starts from the negative.
See the docs:
The int data type is a 32-bit signed two's complement integer. It has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive)
This question already has answers here:
Multiplication of two ints overflowing to result in a negative number
(5 answers)
Closed 9 years ago.
public class Test {
public static void main(String[] args) {
int sum=0;
for(int i=1;i<10;i++)
sum = sum+i*i*i*i*i*i*i*i*i*i;
System.out.println(sum);
}
}
OUTPUT:619374629
for(int i=1;i<10;i++)
sum = sum+i*i*i*i*i*i*i*i*i*i*i;
System.out.println(sum);
OUTPUT:
-585353335
In the second output i thought the integer range crossed.But why it is giving -ve number.It need to give me an error.What is the reason for this behaviour?
Thanks in advance...
You have overflowed the size of a 32 bit integer.
Consider what happens when i is equal to 10:
sum = sum + 100000000000 //1 with 11 zeroes
But the maximum positive number that can be stored in a 32 bit integer is only about 2 billion (2 with nine zeroes).
In fact, it gets even worse! The intermediate calculations will be performed with limited precision, and as soon as the multiplication of 10*10*10*10... overflows, then the 10s will be being multiplied with a weird negative number, and be already wrong.
So the number you end up with is not seeming to follow any rules of arithmetic, but in fact it makes perfect sense once you know that primitive integers have limited storage.
The solution is to use 64-bit long and hope you don't overflow THAT too, if you do then you need BigInteger.
Java defines integer math as signed 2s-complement mod 2^32 (for int) and 2^64 (for long). So any time that the result of an int multiply is 2^31 or higher, it wraps around and becomes a negative number. That's just the way integer math works in java.
Java spec
You are using the primitive type. So, when an integer overflows, it will only print out the bits contained in it which is negative. If you want error, try Integer.
As you predicted, you passed the integer range, though causing infinite values (as the sign [the highest bit] gets touched).
Can someone explain why do I get NumberFormatException.forInputString for this:
string: "01000000000000000000000000000001"
Integer.parseInt(string, 10)
and how can I fix it, when I need the positive int representation of the number?
Thanks
The "01000000000000000000000000000001" is not a valid int.
int has a minimum value of -2,147,483,648 and a maximum value of 2,147,483,647 (inclusive).
You can convert it to BigInteger:
BigInteger myInt = new BigInteger(myString);
Integer.parseInt parses a number into an int, which is a 32-bit signed integer. The number 1000000000000000000000000000001 is far too large to fit in an int.
The largest number you can store in an int is 2,147,483,647 (231 - 1).
That's going to exceed Integer.MAX_VALUE. From the doc:
A constant holding the maximum value an int can have, 231-1.
which is 2147483647
BigInteger may be of use to you here, since it'll store an integer of arbitrary precision i.e. practically unbounded.
This number is way bigger than Integer.MAX_VALUE.
Input number(01000000000000000000000000000001) is greater than Interger.MAX_VALUE, is not parse-able string.
Any value more than 2147483647 and less than -2147483648 is not valid integer.
Find more on Documentation