When we write:
System.out.println(-1);
Does Java consider -1 as Integer or String?
If you follow the documentation, you find:
public void println(int x)
Prints an integer and then terminate the line. This method behaves as though it invokes print(int) and then println().
Then the print(int) documentation says:
The string produced by String.valueOf(int) is translated into bytes according to the platform's default character encoding, and these bytes are written in exactly the manner of the write(int) method.
So it converts the integer to a String before converting that to bytes and printing it out.
Does Java consider -1 as Integer or String?
Neither. -1 is a primitive int literal.
Why is -1 a primitive int literal?
int: By default, the int data type is a 32-bit signed two's complement integer, which has a minimum value of -231 and a maximum value of 231-1.
Also:
Integer literals can be expressed by these number systems:
Decimal: Base 10, whose digits consists of the numbers 0 through 9; this is the number system you use every day
Hexadecimal: Base 16, whose digits consist of the numbers 0 through 9 and the letters A through F
Binary: Base 2, whose digits consists of the numbers 0 and 1 (you can create binary literals in Java SE 7 and later)
See Primitive Data Types
Take a look at the official documentation: System.out.println can accept a lot of parameters, and since you're passing -1 and this has int type, then the method called in your case is public void println(int x).
Behind the scenes though, the -1 is converted into String then into the bytes representation, according to your platform's default character encoding before being sent to the console.
Actually, to be technical- it is neither. Integer is specific to an Integer object in java (As in ArrayList<Integer>) An Integer object is not the same as an int. Your print statement considers the argument as an int.
ArrayList<Integer> integers = new ArrayList<Integer> ();
integers.add(FooIntegerObject);
System.out.print(-1); //is an int
System.out.print("-1"); //is a String
System.out.print(integers(0).toString()); //is an Integer
Related
When I do
Long.parseUnsignedLong("FBD626CC4961A4FC", 16)
I get back -300009666327239428
Which seems wrong, since the meaning of unsigned long according to this answer https://stackoverflow.com/a/2550367/1754020 is that the range is always positive.
To get the correct number from this HEX value I do
BigInteger value = new BigInteger("FBD626CC4961A4FC", 16);
When I print value it prints the correct value. but if I do value.longValue()
again I get the same -300009666327239428 is this of the number being too big and overflowing ?
Java 8 does (somewhat) support unsigned longs, however, you can't just print them directly. Doing so will give you the result that you saw.
If you have an unsigned long
Long number = Long.parseUnsignedLong("FBD626CC4961A4FC", 16);
you can get the correct string representation with the function
String numberToPrint = Long.toUnsignedString(number);
If you now print numberToPrint you get
18146734407382312188
To be more exact, your number is still going to be a regular signed long which is why it shows overflow if printed directly. However, there are new static functions that will treat the value as if it was unsigned, such as this Long.toUnsignedString(long x) or Long.compareUnsigned(long x, long y).
The hexadecimal number "FBD626CC4961A4FC", converted to decimal, is exactly 18146734407382312188. That number is indeed larger than the maximum possible long, defined as Long.MAX_VALUE and which is equal to 263-1, or 9223372036854775807:
System.out.println(new BigInteger("FBD626CC4961A4FC", 16)); // 18146734407382312188
System.out.println(Long.MAX_VALUE); // 9223372036854775807
As such, it's normal that you get back a negative number.
You do not have an exception, as it is exactly the purpose of those new *Unsigned* methods added in Java 8, to give the ability to handle unsigned longs (like compareUnsigned or divideUnsigned). Since the type long in Java is still unsigned, those methods work by understanding negative values as values greater than MAX_VALUE: it simulates an unsigned long. parseUnsignedLong says:
An unsigned integer maps the values usually associated with negative numbers to positive numbers larger than MAX_VALUE.
If you print a long that was the result of parseUnsignedLong, and it is negative, all it means is that the value is greater than the max long value as defined by the language, but that methods taking unsigned longs as parameter will correctly interpret those values, as if they were greater than the max value. As such, instead of printing it directly, if you pass that number to toUnsignedString, you'll get the right output, like shown in this other answer. Not all of these methods are new to Java 8, for example toHexString also interprets the given long as an unsigned long in base 16, and printing Long.toHexString(Long.parseUnsignedLong("FBD626CC4961A4FC", 16)) will give you back the right hex String.
parseUnsignedLong will throw an exception only when the value cannot be represented as an unsigned long, i.e. not a number at all, or greater than 264-1 (and not 263-1 which is the maximum value for a signed long).
Yes, it overflows when you are trying to print it, as it is converted to Java long type. To understand why let's take log2 of your dec value.
First thing, original value is 18146734407382312188. It's log2 is ~63.9763437545.
Second, look into documentation: in java long type represents values of -2^63 and a maximum value of 2^63-1.
So, your value is obviously greater then 2^63-1, hence it overflows:
-2^63 + (18146734407382312188 - 2^63 + 1) = -300009666327239428
But as #Keiwan brilliantly mentioned, you still can print proper value using Long.toUnsignedString(number);
Internally unsigned and signed numbers are represented in the same way, i.e. as 8 bytes in case of a long. The difference only how the "sign" bit interpreted, i.e. if you'd do the same in a C/C++ program and store your value into an uint64_t then cast/map it to a asigned int64_t you should get the same result.
Since the maximum value 8 bytes or 64 bits can hold is 2^64-1 that's the hard constraint for such numbers. Also Java doesn't directly support unsigned numbers and thus the only way to store an unsigned long in a long is to allow for a value that's higher than the signed Long.MAX_VALUE. In fact Java doesn't know whether the string/hexcode you're reading is meant to represent a signed or unsigned long so it's up to you to provide that interpretation, either by converting back to a string or using a larger datatype such as BigInteger.
Say I have two integers, one in decimal the other in hexadecimal:
int myInt01 = 0xc7d23020;
int myInt02 = 3352440864;
The are both the same number, but when I try to assign the decimal integer to a variable in Java, I get the error:
error: integer number too large: 3352440864
But when I assign the hexadecimal integer to a variable in Java, everything works as it should.
Why is it this way?
That's because 0xc7d23020 is interpreted as -942526432 which is a valid int value, while 3352440864 is clearly a wrong int value because it's higher than the limit 2147483647;
I guess this is intended behavior: The binary representation of this number has the most significant bit set, in a 32 bit datatype. Since in Java int is a signed datatype, the most significant bit is reserved for the sign of the number. Thus, the number is not a valid positive number. This is what the compiler is telling you. However, since it is a valid negative integer, it does not complain when you assign it using the hex-representation.
You can try assigning a number that would need more than 32 bits to an integer variable using the hex-representation. This will lead to a compiler error.
The max value that a int variable can hold is 2147483647. That's why it is giving that error. You can check that out yourself by doing this: System.out.println(Integer.MAX_VALUE);
To find out the minimum value that a int variable can hold System.out.println(Integer.MIN_VALUE);
Question:
This code in Java:
BigInteger mod = new BigInteger("86f71688cdd2612ca117d1f54bdae029", 16);
produces (in java) the number
179399505810976971998364784462504058921
However, when I use C#,
BigInteger mod = BigInteger.Parse("86f71688cdd2612ca117d1f54bdae029", System.Globalization.NumberStyles.HexNumber); // base 16
i don't get the same number, I get:
-160882861109961491465009822969264152535
However, when I create the number directly from decimal, it works
BigInteger mod = BigInteger.Parse("179399505810976971998364784462504058921");
I tried converting the hex string in a byte array and reversing it, and creating a biginteger from the reversed array, just in case it's a byte array with different endianness, but that didn't help...
I also encountered the following problem when converting Java-Code to C#:
Java
BigInteger k0 = new BigInteger(byte[]);
to get the same number in C#, I must reverse the array because of different Endianness in the biginteger implementation
C# equivalent:
BigInteger k0 = new BigInteger(byte[].Reverse().ToArray());
Here's what MSDN says about BigInteger.Parse:
If value is a hexadecimal string, the Parse(String, NumberStyles) method interprets value as a negative number stored by using two's complement representation if its first two hexadecimal digits are greater than or equal to 0x80. In other words, the method interprets the highest-order bit of the first byte in value as the sign bit. To make sure that a hexadecimal string is correctly interpreted as a positive number, the first digit in value must have a value of zero. For example, the method interprets 0x80 as a negative value, but it interprets either 0x080 or 0x0080 as a positive value.
So, add a 0 in front of the parsed hexadecimal number to force an unsigned interpretation.
As for round-tripping a big integer represented by a byte array between Java and C#, I'd advise against that, unless you really have to. But both implementations happen to use a compatible two's complement representation, if you fix the endianness issue.
MSDN says:
The individual bytes in the array returned by this method appear in little-endian order. That is, the lower-order bytes of the value precede the higher-order bytes. The first byte of the array reflects the first eight bits of the BigInteger value, the second byte reflects the next eight bits, and so on.
Java docs say:
Returns a byte array containing the two's-complement representation of this BigInteger. The byte array will be in big-endian byte-order: the most significant byte is in the zeroth element.
Integer b = Integer.valueOf("444",8);
System.out.println(b);
why b=292 I can't understand this static function
and when
b=Integer.valueOf("444",16);
System.out.println(b)
why b=1092
I appreciate your help
Thanks in advance
As usual sigh the docs are there to read them. http://docs.oracle.com/javase/7/docs/api/java/lang/Integer.html#valueOf%28java.lang.String,%20int%29
Returns an Integer object holding the value extracted from the specified String when parsed with the radix given by the second argument.
This means, if you pass 16 as second argument, the number will be interpreted as a hexadecimal number, thus: 4 * 16 ^ 2 + 4 * 16 + 4 = 1092. Same for octal, only with radix 8.
You are providing the radix as octal and hexa so you are getting the output as per the radix provided:
static Integer valueOf(String s, int radix)
As per the java documentation Integer.valueOf:
Returns an Integer object holding the value extracted from the
specified String when parsed with the radix given by the second
argument. The first argument is interpreted as representing a signed
integer in the radix specified by the second argument, exactly as if
the arguments were given to the parseInt(java.lang.String, int)
method. The result is an Integer object that represents the integer
value specified by the string.
Because 444 in base 8 = 292 in base 10 and 444 in base 16 = 1092 in base 10.
"444" is the string and 16 is called as the radix, one thing to be noted is that decimal is the default base.
Now the radix is the present base of the argument in this case its 16 i.e. hex which needs to be converted to default i.e. decimal so
444(hex) to decimal is 1092.
Although it is a very Initial level question but I find it complex one. Actually I want to know what is happening behind the scene? Why Character.MAX_VALUE does not print the Max Value of char(Which is 65535) and MAX_VALUE-1 does.
System.out.println("Byte Max Value: "+Byte.MAX_VALUE);//print 127 Ok!
System.out.println("Character Max Value: "+Character.MAX_VALUE);//print ?(Question Mark)
System.out.println(Character.MAX_VALUE-1);//print 65534
Because in the second line, Character.MAX_VALUE is concatenated with the String.
As the JLS states:
The string concatenation operator + (§15.18.1), which, when given a
String operand and an integral operand, will convert the integral
operand to a String representing its value in decimal form, and then
produce a newly created String that is the concatenation of the two
strings
As Character.MAX_VALUE is not printable, you don't see it.
In the third case, your doing a substraction with an int, thus the whole expression is casted to int and it prints an int value.
Also as the JLS states:
The binary + operator performs addition when applied to two operands
of numeric type, producing the sum of the operands.
[...]
Binary numeric promotion is performed on the operands (§5.6.2).
When an operator applies binary numeric promotion to a pair of operands, each of which must denote a value that is convertible to a numeric type, the following rules apply, in order:
[...]
Widening primitive conversion (§5.1.2) is applied to convert either or
both operands as specified by the following rules:
If either operand is of type double, the other is converted to double.
Otherwise, if either operand is of type float, the other is converted
to float.
Otherwise, if either operand is of type long, the other is converted
to long.
Otherwise, both operands are converted to type int.
If you've done
System.out.println("Character Max Value: "+(Character.MAX_VALUE+0));
It would print Character Max Value: 65535
Character.MAX_VALUE is \uFFFF. This is not a printable character by definition. When you perform an operation like -1 or +1 you are changing the type to an int
http://www.fileformat.info/info/unicode/char/ffff/index.htm
Implicit casting by adding 0 to Character.MIN_VALUE or Character.MAX_VALUE works well.
You can also explicitly cast to an int, to get the MIN_VALUE and MAX_VALUE With two println() methods....
System.out.println("char min. value: " + (int)Character.MIN_VALUE);
System.out.println("char max. value: " + (int)Character.MAX_VALUE);
In your third line you have...
System.out.println(Character.MAX_VALUE-1);//print 65534
You are essentially implicitly casting the Unicode maximum value to an int and then subtracting 1 from that maximum value. In Unicode format the range is from U+0000 to U+FFFF, the FFFF (65535) is the numeric upper range of the char primitive data type and 0000 (0) is the numeric lower range of the char data type. In the two println() methods above, is the Character class which is the wrapper class for the char primitive data type, it simply takes the primitive char and wraps it up in the Character class. Allowing us to treat it as an object and giving us access to the fields and methods of the Character wrapper class.
Then using the MIN_VALUE and MAX_VALUE fields with the dot operator we can cast these Unicode values to int's and the output is the range expressed as decimal numbers is 0 to 65535
Of course it is understood that if something can be implicitly cast it can also be explicitly cast.
We are also only considering here the Basic Multilingual Plane (Plane 0). Normally a Unicode code point is referred to by writing "U+" followed by its four digit hexadecimal number. So these code points in Plane 0 are expressed by a four digit hexadecimal number, nothing to difficult. The Unicode code points are nothing more than four digit hexadecimal numbers. Plane 0 has a range of 65535 possible characters that it can represent. Wikipedia has a good article on Unicode.
http://en.wikipedia.org/wiki/Unicode