From javadoc, I understand that Java, by default, has int data type as a 32-bit signed two's complement integer, which has a minimum value of -2^31 and a maximum value of 2^31-1.
If that is the case, why does this:
System.out.println(Integer.parseInt("1111", 2));
give a value of 15 instead of -1(2's complement signed number).
You've made an assumption that, because integers are represented internally using two's complement, Integer.parseInt with a radix of 2 (binary) also takes numbers in that form. That assumption was incorrect.
Your best bet with stuff like this is to read the documentation. There's no mention of two's complement. It does however say:
the first character may be an ASCII minus sign '-' ('\u002D') to
indicate a negative value
So if you want to parse values represented using two's complement, you will have to write a function which converts the binary number to the absolute value, then appends a minus if necessary.
According to the javadoc of java.lang.Integer class parseInt(String s, int radix) method does the following;
Parses the string argument as a signed integer in the radix specified
by the second argument. The characters in the string must all be
digits of the specified radix.
When you run;
System.out.println(Integer.parseInt("1111", 2));
You are telling the method to take "1111" as a string and convert it to an int value with a base of 2(your radix), eventually it sums to 15 in binary.
Your input "1111" is actually a shortcut to this string "0000 0000 0000 1111", which represent 15.
For the method Integer.parseInt(binaryString, 2), if your binaryString's first char is not '-', then it means parse an unsigned int.
Related
I have a quick question about the Char data type. It's about an exercise from university, I'm not allowed to use any prefabricated Java methods, such as parse int or something.
In the exercise, you have a char array that represents hexadecimal numbers and has this content, for example:
char[] test={'0','x','F','F'); or char[] test={'F','F',);
and now I should convert this char to a long. But before that, I should check if my hexadecimal number, is convertible to a long. So simplified the task says I should check if my hexadecimal number, which I am given as a char, can be converted into a long.
AND now we come to my problem.
If I want to convert this char into a long, I first check whether this is allowed. A char has 16 bits and a long 64 bits. That means I can only convert 4 chars to a long or (64/16=4)? Is that what they mean by check if you can convert the char into a long value?
If so, so if I am to check the bits is it correct that I do this with 16 bits? Because later when I convert my array of chars to a long, I do it with the integer or not? e.g. F is 70 when I look to my char, and 70 is represent as an integer.
Because when I make my char a long value, I do that via the integer representation of the char, right? And then I don't actually have a char any more, but an integer with 32 bits.
And an integer has 32 bits, does that mean I can only convert 2 char values to a long?
Look at
char[] test={'0','x','F','F');
char[] test={'F','F',);
Evidenty they want
long n = 0xFFL = 255L;
in both cases "0x" being optional.
So a character array containing a text representation of a hexadecimal number,
converted to long.
That is a totally different
Since each hexadecimal digit corresponds to exactly 4 bits of the the resulting integer respectively long value, all you have to do is check the number of digits. For a 16-bit integer, you can have at most 4 hexadecimal digits. For 32-bit integer, 8 hexadecimal digits are allowed; and for 64-bit integer (aka long), 16 hexadecimal digits are the limit.
Since Java does not support unsigned types, the most significant digit must be '7' or lower if your number uses the maxium allowed number of digits.
Please keep in mind that the prefix {'0','x' does not count towards the allowed number of digits.
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).
System.out.println(Byte.toString( (byte)(1 << 7) ));//print "-128"
System.out.println(Byte.parseByte("80", 16));//run time exception java.lang.NumberFormatException: Value out of range. Value:"80" Radix:16
Why does the first succeed while the second fails? One might expect that they produce the same output.
Hexadecimal 0x80 is 128 in decimal. Bytes can only hold values from -128 to 127, inclusive. So, when you try to parse a value of 128, it fails because that value can't be represented as a byte.
If you want to parse a negative value, you need to include a negative sign:
System.out.println(Byte.parseByte("-80", 16)); /* Prints -128 */
When performing a narrowing conversion, for example, from int to byte as in this example, information about the overall magnitude of a value can be lost. Casting an int value to byte simply discards all but the lowest 8 bits, so casting int 128 to byte yields -128.
The first operator is a binary shift. -128 represents 0b10000000 in binary code. The 1 shifted seven times to the left.
In the second statement, the radix you're using is for hex numbers as you can see in Tutorialspoint's example. If you change your statement to System.out.println(Byte.parseByte("80", 10));, you won't get the exception.
Hope this explanations was of help.
Why are this two methods using two different approaches while processing binary numbers? String which represents negative binary number in Integer.parseInt(String s, 2) method should start with - character, but Integer.toBinaryString(int i) returns string with additional 1 ahead. So, this code
Integer.parseInt(Integer.toBinaryString(-1), 2);
throws java.lang.NumberFormatException. What is the reason of such behavior?
This is by design; Integer.toBinaryString
Returns a string representation of the integer argument as an unsigned integer in base 2.
(emphasis added).
I.e., toBinaryString provides a way to format an integer as the common two's complement representation, which is the way most processors actually store signed integers internally.
Integer::parseInt(String,int) is expecting a string and so it is looking for the - symbol in negative number. Whereas the Integer::toBinaryString(int) is for giving you the binary equivalent of your input. In Binary, negative numbers are represented by 2's Compliment.
I have the following code:
Why does Java think that this is not a valid long.
#Test
public void testOffendingBinaryString() {
String offendingString = "1000000000000000000010101000000000000000000000000000000000000000";
assertEquals(64, offendingString.length());
Long.parseLong(offendingString, 2);
}
Because it's out of range for the valid value of a long. The string:
"-111111111111111111101011000000000000000000000000000000000000000"
should work just fine. You cannot specify a negative number directly in 2s complement binary notation. And if you're trying to specify a positive number, that number is too big to fit into a Java long, which is a signed 64-bit value expressed in 2s complement (which means it's basically 63 bits + a sign bit (it's a little more complicated than that, read the page on 2s complement)).
The long is stored in 2's compliment, but the parse method expects straight binary. So, the max number of digits in the String can be 63.
When using regular binary, there is no sign bit. You can pass it a String with length 63 and precede it with a - if you want a negative long.
This is a bug in Java, see http://bugs.sun.com/bugdatabase/view_bug.do?bug_id=4215269, they fixed it in 1.8
Java long type:
8 bytes signed (two's complement).
Ranges from -9,223,372,036,854,775,808
to +9,223,372,036,854,775,807.
The size of the string is too long, check this question
Internally numbers are represented using the Two's complement. That means there are only 63 bits, for the number and one bit to represent positive or negative numbers. Since Long.parseLong() is not ment to parse numbers in Two's complement your String is a positive number with 64 bits, that exceeds the maximum positive value for a long.