How to compute absolute value of signed random integer - java

I'm trying to generate the random number which is stored and I need to return the string value.
Here is My method:
public String generateRand() {
java.util.Random rand = new java.util.Random(System.currentTimeMillis());
String rnd = "" + Math.abs(rand.nextInt()) + "" +
Math.abs(System.currentTimeMillis());
return rnd;
}
The Findbugs plugin of Jenkins is warning me that there is Bad attempt to compute absolute value of signed random integer.
This code generates a random signed integer and then computes the absolute value of that random integer. If the number returned by the random number generator is Integer.MIN_VALUE, then the result will be negative as well, since Math.abs(Integer.MIN_VALUE) == Integer.MIN_VALUE.
Same problem arised for long values as well.
What is the best way to to compute absolute value of signed random integer?

Use
rand.nextInt(Integer.MAX_VALUE);
instead of
Math.abs(rand.nextInt())

Consider a byte. Its value ranges from -128 to 127. Say your byte has a value of -100, then Math.abs(-100) will give you 100. But what if the value of your byte is -128? You cannot represent 128 as a byte, since the maximum value it can represent is 127. So Math.abs() simply returns the negative parameter, unchanged.
The moral of the story is that it's possible for Math.abs() to return a negative value.

Sounds like the plugin recognizes the specific case, Math.abs(rand.nextInt()). So write something different.
The plug-in knows that that case doesn't always work: It knows that rand.nextInt() can sometimes return Integer.MIN_VALUE, and it knows that Math.abs(Integer.MIN_VALUE) can not be computed. I would think about writing my own random number function that does not ever return Integer.MIN_VALUE.

Related

How to Integer overflowed value when Integer is drived from Integer.parseInt("2147483647");

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.

DIfference between signed and unsigned practically

I've searched and read many previous answers concerning this difference but I still don't get somethings, for example with this line of code :
System.out.println(Integer.parseUnsignedInt("11111111111111111111111111111111", 2));
I read that Unsigned can hold a larger positive value, and no negative value. Unsigned uses the leading bit as a part of the value, while the signed version uses the left-most-bit to identify if the number is positive or negative. signed integers can hold both positive and negative numbers. A Unisgned can go larger than MAX_VALUE, so why is that sysout gives -1 which is negative. And for this line code :
System.out.println(Integer.parseInt("11111111111111111111111111111111", 2));
Why does this line gives an error(32 times 1) ? Isn't a signed int suppose to treat the first 1 as a minus, and the other 31 1's as the positive value ? (so it should give - MAX_VALUE)
Java does not have unsigned integer types. When you call parseUnsignedInt, it does not return an unsigned integer, because there is no such thing in java.
Instead, parseUnsignedInt parses the input as an unsigned 32-bit value, and then returns the signed 32-bit value with the same bits.
If you provide it with a number that has the leading bit set in its unsigned representation, it will therefore return a negative number, because all the signed numbers with that bit set are negative.
Why does this line gives an error(32 times 1) ? Isn't a signed int
suppose to treat the first 1 as a minus, and the other 31 1's as the
positive value ? (so it should give - MAX_VALUE)
It throws a NumberFormatException for exactly the same reason that
Integer.parseInt("2147483648", 10)
does. The string does not represent a number that can be represented as an int when interpreted according to the specified radix. That int uses 32 bits to represent values is only peripherally related. If you want to parse a negative value with Integer.parseInt() then the string should contain a leading minus sign:
Integer.parseInt("-1111111111111111111111111111111", 2)
or even
Integer.parseInt("-10000000000000000000000000000000", 2) // note: 32 digits
The method is not mapping bits directly to an int representation. It is interpreting the string as a textual representation of a number.
A Unsigned can go larger than MAX_VALUE, so why is that sysout gives
-1 which is negative.
Integer holds a 32-bit value. The result of parseUnsignedInt(32 one-bits, 2) is a value with all bits set. What that "means" is in the eye of the beholder. Most of Java considers integer values to be signed. The formatter used by println, for example, regards the value as signed, and the result is -1.
All you really have 'inside' the Integer is a 32-bit value. parseUnsignedInt() handles its input argument specially, but then it has to store the result in a standard Integer. There is nothing to say that the bits are supposed to be 'unsigned'. If you want to treat the value as unsigned, you can't use anything that treats it as signed, since Java really does not have an unsigned-integer type.
Isn't a signed int suppose to treat the first 1 as a minus, and the
other 31 1's as the positive value ? (so it should give - MAX_VALUE)
See other answer for this part.
The representation I think you were expecting, where the high bit indicates the sign and the rest of the bits indicates the (positive) value, is called "sign and magnitude" representation. I am unaware of any current computer that uses sign-and-magnitude for its integers (may have happened in the very early days, 1950s or so, when people were getting to grips with this stuff).

how to make -2147483648 a positive number in Java?

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.

Converting negative integer to hex value using pre-defined methods

I am a beginner in Java, and have just started learning this language.
I am learning and experimenting with examples from Herbert Schildt's book to test my understanding.
My objective is to convert negative integer to hex using in-built java methods, and then back to integer (or long). However, there are two issues that I am facing:
Issue #1: as I understand from the thread hex string to decimal conversion, Java Integer parseInt error and Converting Hexadecimal String to Decimal Integer that the converted value fffffff1 is too big to fit into Integer, so I have used Long. However, when fffffff1 is converted back to Long, I don't get -15. I get garbage value = 4294967281.
Moreover, when I type-cast the result from Long to Integer, it works well. I am not sure why Long result would show garbage value and then magically I would get the right value by just typecasting the number to integer-type. I am sure I am missing something crucial here.
Issue#2: If I don't use radix (or even change it from 16 to 4) in the method Long.parseLong(), I get an exception.
Here's my code:
public class HexByte {
public static void main(String[] args) {
byte b = (byte) 0xf1;
System.out.println("Integer value is:"+Integer.valueOf(b)); //you would get -15
int i = -15;
System.out.println("Hexadecimal value is:"+Integer.toHexString(i));
//Let's try to convert to hex and then back to integer:
System.out.println("Integer of Hexadecimal of -15 is:"+(int)Long.parseLong(Integer.toHexString(i),16 ));
//type-cast to integer works well, but not sure why
System.out.println("Integer of Hexadecimal of -15 is:"+Long.parseLong(Integer.toHexString(i),16));
//This surprisingly throws garbage value
System.out.println("Integer of Hexadecimal of -15 is:"+Long.parseLong(Integer.toHexString(i)));
//doesn't work - throws an exception
}
}
Can someone please help me? I didn't want to open duplicate threads for above issues so I have included them herewith.
Issue 1:
Negative numbers are represented using Two's Complement, which you can read more about here: wikipedia link
Basically, the left-most bit is used to determine the sign of the integer (whether it's positive or negative). A 0 means the number is positive, and a 1 means it's negative.
fffffff1 doesn't go all the way to the left, so the left-most bit when you convert that to long is a 0, which means the number is positive. When you cast it to an integer, the left bits are just dropped, and you end up somewhere in the middle of the 1s such that your leftmost digit is now a 1, so that the result is negative.
An example, with much shorter lengths for demonstration's sake:
4-bit number: 0111 -> this is positive since it starts with a 0
2-bit number using the last 2 bits of the 4-bit number: 11 -> this is negative since it starts with a 1.
Longs are like the 4-bit number in this example, and ints are like the 2-bit number. Longs have 64 bits and ints have 32 bits.
Issue 2:
If you don't specify a radix, Long.parseLong assumes base 10. You're giving it "fffffff1", and it doesn't recognize "f" as a digit in base 10 and thus throws an exception. When you specify the radix 16 then it knows "f" = 15 so there aren't any problems.

Java sum 2 negative numbers

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);

Categories

Resources