Java int issue while intializtion - java

I have been working on a project and i saw some references on web and they initialized :
int val= 0x000; output 0
int val1= 0x001; output 1
How exactly java is converting this?
Thanks

It's an hexadecimal (base 16 instead of base 10). Hexadecimals starts with 0x.... And it can contain these digits: 0123456789ABCDEF
Octals (base 8) starts with 0... and can containt digits less than 8 (01234567)
int dec = 123; // decimal: 1*(10^2) + 2*(10^1) + 3*(10^0) = 123
int oct = 0123; // octal: 1*(8^2) + 2*(8^1) + 3*(8^0) = 83
int hex = 0x123; // hexadecimal: 1*(16^2) + 2*(16^1) + 3*(16^0) = 291

You can do int val = 0; and int val = 1; with decimal notation..
The 0x before the number indicate an hexadecimal notation...
All notations are:
0b to binary: int i = 0b10101010110;
nothing to decimal: int i = 123;
0 to octal: int i = 0123345670;
0x to hexadecimal: int i = 0xAEF123;

As a matter of fact, Java does not "convert" but "interpret" the values (as hexadecimal).

Numbers starting with 0x are hexadecimal. Java converts them (like decimal ones, too) to binary and saves them.

This hexadecimal number system (base 16)
Start with 0x...
(Octals start with 0...)
Link

Related

Array of Bytes (as hex) conversion to Int issue. (Kotlin/Java)

I'm looking at parsing information from a temp/humidity sensor that was provided with the following instructions;
There are 6 bytes.
Temperature positive/negative: 0 means positive (+) and 1 means negative (-)
Integer part of temperature. Show in Hexadecimal.
Decimal part of temperature. Show in Hexadecimal.
Reserved byte. Ignore it.
Integer part of humidity. Show in Hexadecimal.
Decimal part of humidity. Show in Hexadecimal.
For example: 00 14 05 22 32 08 means +20.5C 50.8% & 01 08 09 00 14 05
means -8.9C 20.5%
as each byte is in hex & i need to covert this to an Int I followed this approach - Java code To convert byte to Hexadecimal but the values I get when validating their example don't make sense.In Kotlin I do;
val example = byteArrayOf(0, 14, 5, 22, 32, 8)
example.map { Integer.parseInt(String.format("%02X ", it),16)}
First Example output is;
0 = "00 "
1 = "08 "
2 = "09 "
3 = "00 "
4 = "0E "
5 = "05 "
Second Example output;
0 = "00 "
1 = "0E "
2 = "05 "
3 = "16 "
4 = "20 "
5 = "08 "
What am I doing wrong? I'm starting to think the manufactures instructions could be 'misleading'
A key thing you are missing here is that when passing in the it parameter to String#format, that value is a decimal int, not a hexadecimal int.
You instead want to map the value in the array directly to a string, then get its decimal value:
byte it = 14;
int x = Integer.parseInt(String.valueOf(it), 16);
System.out.println(x); // This will print 20
This should get you the expected result.
Note, your problem is slightly confusing because the numbers in your byte array are decimal numbers...already in their hex 'format'. There are a few ways this confusion can be fixed (assuming you have control of the array's type and/or contents):
Use String instead of byte
String it = "14";
int x = Integer.parseInt(it, 16);
System.out.println(x); // This will print 20
Store the values as hex and still convert (i.e., putting a 0x in front of each number)
byte it = 0x14;
int x = Integer.parseInt(String.format("%02X", it), 16);
System.out.println(x); // This will print 20
Store the values as hex and don't convert, because there is no need
byte it = 0x14;
System.out.println(it); // This will print 20
If you go with the second bullet, though convoluted, what you have right now should work, but the third option would be best if you are hardcoding in the byte array's values.

Android studio - byte operations - changing value

I have a problem with bit operations
int progress = slider.getProgress(); value of user input
then I have to do shift left and change it to HEX
int shl = 1<<progress-1;
String hexStr = Integer.toHexString(shl);
Nex Im sending bytes by BT
byte bit = Byte.decode(hexStr)
command[2]=bit;
Now the problem
If user set for example 2 it is ok 0b100 = 0x04
But if user set 5 0b10000 = hexStr = 10 in command[2] it gets value 0x0A
Why is it changing value?
"But if user set 5 0b10000 = hexStr = 10 in command[2] it gets value = 0x0A.
Why is it changing value?"
It is correct. What different result are you expecting?
For example : If progress is 5 then...
Doing bit shift like 1 << progress-1 == 1 << 4 = (resulting bits= 0001 0000) which gives :
int shl = 10 in hex format or even int shl = 16 in decimal format
Doing String hexStr = Integer.toHexString(shl); puts shl's "10" hex string value to the other string hexStr (ie: is also now a "10")...
Doing byte bit = Byte.decode(hexStr) makes a byte with a decimal value of hexStr's "10".
This is how your result is command[2] saying hex value of 0x0A which == decimal value of 10.
....
"I'm not translating decimal to binary or hex, but the user input which tells on which position "1" should go. Hope it's clear..."
Why not just write "1" and then add as many zeroes as required (padding)?
Note: I'm not sure what value command[2]= is supposed to get. Maybe it checks the 8 bits of that byte, or maybe it expects a number (integer). It's confusng becuase your numbers rely on "1 followed by zeroes", also binary can be "1 followed by zeroes"
Binary : There are 8 bits in a byte, so the max binary you can send is 10000000 only.
Integer : A single byte is signed so the max value s 128. By this logic your options are 1, 10, 100 only.
See if this helps (check which command[2]= you want. I've commented // them out for now) :
int progress = 5;
int shl = 1 << progress-1; //why??
String hexStr = Integer.toHexString(shl);
String shlStr = Integer.toString(shl);
String zeroStr = "";
byte bit = Byte.decode(hexStr);
//command[2]=bit;
System.out.println("shl result string : " + shlStr);
System.out.println("Bytes string hex : " + hexStr);
//# Padding
for(int i = 0; i < (progress-1); i++)
{ zeroStr += "0"; }
shlStr = "1" + zeroStr;
//command[2]= Byte.decode(shlStr);
System.out.println("Result string hex : " + zeroStr);
System.out.println("shi padding string : " + shiStr);

Convert int which start with leading zero to string

I'm trying to convert int's which start with 0 to strings to be stored in a phone directory as the telephone numbers can start with 0.
I've tried -
int num = 0125;
String.format("%04d",num);
and
Integer.toString(num);
and
DecimalFormat df = new DecimalFormat("0000");
df.format(num);
Each time I get the output 0085 rather than 0125.
How do I convert an int with a leading zero to a string in decimal format?
An int value starting with a zero is considered to be a octal number (having numbers from 0 - 7) similar to hexadecimal numbers. Hence your value:
0125
is equal to: 1 * 82 + 2 * 81 + 5 * 80 == 64 + 16 + 5 == 85
Don't try to represent a phone-number as an int. Instead use a String and validate it using a regex expression. If you combine both, you may as well represent a phone number by its own type like:
public class PhoneNumber {
private final String number;
public PhoneNumber(String number) {
if (number == null || !number.matches("\\d+([-]\\d+)?")) {
throw new .....
}
this.number = number;
}
}
The regex is just an example matching phone numbers like: 1234 or 0123-45678.
A numeric literal that starts with 0 is considered to be Octal (base 8). 125 base 8 is 85 base 10 (decimal).
Also, int i = 09 will throw a compiler error for the same reason.
See 09 is not recognized where as 9 is recognized
0125 is actually 85. Why?
Numbers that starts with 0, are octal numbers. So 0125 is:
5*80 + 2*81 + 1*82 = 85
See the JLS - 3.10.1. Integer Literals:
An octal numeral consists of an ASCII digit 0 followed by one or more
of the ASCII digits 0 through 7 interspersed with underscores, and can
represent a positive, zero, or negative integer.

Java converting int to hex and back again

I have the following code...
int Val=-32768;
String Hex=Integer.toHexString(Val);
This equates to ffff8000
int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
int SecondAttempt=Integer.decode("0x"+Hex); // Error "Invalid Int"
So, initially, it converts the value -32768 into a hex string ffff8000, but then it can't convert the hex string back into an Integer.
In .Net it works as I'd expect, and returns -32768.
I know that I could write my own little method to convert this myself, but I'm just wondering if I'm missing something, or if this is genuinely a bug?
int val = -32768;
String hex = Integer.toHexString(val);
int parsedResult = (int) Long.parseLong(hex, 16);
System.out.println(parsedResult);
That's how you can do it.
The reason why it doesn't work your way: Integer.parseInt takes a signed int, while toHexString produces an unsigned result. So if you insert something higher than 0x7FFFFFF, an error will be thrown automatically. If you parse it as long instead, it will still be signed. But when you cast it back to int, it will overflow to the correct value.
It overflows, because the number is negative.
Try this and it will work:
int n = (int) Long.parseLong("ffff8000", 16);
int to Hex :
Integer.toHexString(intValue);
Hex to int :
Integer.valueOf(hexString, 16).intValue();
You may also want to use long instead of int (if the value does not fit the int bounds):
Hex to long:
Long.valueOf(hexString, 16).longValue()
long to Hex
Long.toHexString(longValue)
It's worth mentioning that Java 8 has the methods Integer.parseUnsignedInt and Long.parseUnsignedLong that does what you wanted, specifically:
Integer.parseUnsignedInt("ffff8000",16) == -32768
The name is a bit confusing, as it parses a signed integer from a hex string, but it does the work.
Try using BigInteger class, it works.
int Val=-32768;
String Hex=Integer.toHexString(Val);
//int FirstAttempt=Integer.parseInt(Hex,16); // Error "Invalid Int"
//int SecondAttempt=Integer.decode("0x"+Hex); // Error "Invalid Int"
BigInteger i = new BigInteger(Hex,16);
System.out.println(i.intValue());
As Integer.toHexString(byte/integer) is not working when you are trying to convert signed bytes like UTF-16 decoded characters you have to use:
Integer.toString(byte/integer, 16);
or
String.format("%02X", byte/integer);
reverse you can use
Integer.parseInt(hexString, 16);
Java's parseInt method is actally a bunch of code eating "false" hex : if you want to translate -32768, you should convert the absolute value into hex, then prepend the string with '-'.
There is a sample of Integer.java file :
public static int parseInt(String s, int radix)
The description is quite explicit :
* Parses the string argument as a signed integer in the radix
* specified by the second argument. The characters in the string
...
...
* parseInt("0", 10) returns 0
* parseInt("473", 10) returns 473
* parseInt("-0", 10) returns 0
* parseInt("-FF", 16) returns -255
Using Integer.toHexString(...) is a good answer. But personally prefer to use String.format(...).
Try this sample as a test.
byte[] values = new byte[64];
Arrays.fill(values, (byte)8); //Fills array with 8 just for test
String valuesStr = "";
for(int i = 0; i < values.length; i++)
valuesStr += String.format("0x%02x", values[i] & 0xff) + " ";
valuesStr.trim();
Below code would work:
int a=-32768;
String a1=Integer.toHexString(a);
int parsedResult=(int)Long.parseLong(a1,16);
System.out.println("Parsed Value is " +parsedResult);
Hehe, curious. I think this is an "intentianal bug", so to speak.
The underlying reason is how the Integer class is written. Basically, parseInt is "optimized" for positive numbers. When it parses the string, it builds the result cumulatively, but negated. Then it flips the sign of the end-result.
Example:
66 = 0x42
parsed like:
4*(-1) = -4
-4 * 16 = -64 (hex 4 parsed)
-64 - 2 = -66 (hex 2 parsed)
return -66 * (-1) = 66
Now, let's look at your example
FFFF8000
16*(-1) = -16 (first F parsed)
-16*16 = -256
-256 - 16 = -272 (second F parsed)
-272 * 16 = -4352
-4352 - 16 = -4368 (third F parsed)
-4352 * 16 = -69888
-69888 - 16 = -69904 (forth F parsed)
-69904 * 16 = -1118464
-1118464 - 8 = -1118472 (8 parsed)
-1118464 * 16 = -17895552
-17895552 - 0 = -17895552 (first 0 parsed)
Here it blows up since -17895552 < -Integer.MAX_VALUE / 16 (-134217728).
Attempting to execute the next logical step in the chain (-17895552 * 16)
would cause an integer overflow error.
Edit (addition): in order for the parseInt() to work "consistently" for -Integer.MAX_VALUE <= n <= Integer.MAX_VALUE, they would have had to implement logic to "rotate" when reaching -Integer.MAX_VALUE in the cumulative result, starting over at the max-end of the integer range and continuing downwards from there. Why they did not do this, one would have to ask Josh Bloch or whoever implemented it in the first place. It might just be an optimization.
However,
Hex=Integer.toHexString(Integer.MAX_VALUE);
System.out.println(Hex);
System.out.println(Integer.parseInt(Hex.toUpperCase(), 16));
works just fine, for just this reason. In the sourcee for Integer you can find this comment.
// Accumulating negatively avoids surprises near MAX_VALUE

Why are integer literals with leading zeroes interpreted strangely?

This prints 83
System.out.println(0123)
However this prints 123
System.out.println(123)
Why does it work that way?
A leading zero denotes that the literal is expressed using octal (a base-8 number).
0123 can be converted by doing (1 * 8 * 8) + (2 * 8) + (3), which equals 83 in decimal.
For some reason, octal floats are not available.
Just don't use the leading zero if you don't intend the literal to be expressed in octal.
There is also a 0x prefix which denotes that the literal is expressed in hexadecimal (base 16).
Because integer literals starting with 0 are treated as octal numbers.
See section 3.10.1 of the JLS
Try this:
public static String leftPad(int n, int padding) {
return String.format("%0" + padding + "d", n);
}
leftPad(5, 3); // return "005"
leftPad(15, 5); // return "00015"
leftPad(224, 3); // return "224"
leftPad(0, 4); // return "0000"
first one printed as 83 because java takes 0123 as octal number and it prints decimal equivalent of that number.
The octal (leading 0) and hexadecimal (leading 0x) were inherited from C.
For comparison, try
System.out.println(0x123);
In Java integer literals with a leading zero are octal integers (base 8).
(1 * 8^2) + (2 * 8^1) + (3 * 8^0) = 83
So do not use any number leading with 0 if you don't want to treat it as an octal number.
0123 -> 83
1010L -> 1010
0101L -> 65
The numbers 1010L and 0101L are not in binary representation (just to avoid the confusion).
These numbers are in decimal representation.
Even as per the Regex patterns in Oracle docs,
\0n is the character with octal value 0n (0 <= n <= 7)
\xhh is the character with hexadecimal value 0xhh
Thus, your number 0101 be it in Integer or Long format is treated as an Octal representation of a number.
123 => 1 * 8^2 + 2 * 8^1 + 1 * 8^0 = 83
0101 => 1 * 8^2 + 0 * 8^1 + 1 * 8^0 = 64 + 0 + 1 = 65
printf will do it: http://java.sun.com/developer/technicalArticles/Programming/sprintf/
public class X
{
public static void main(final String[] argv)
{
System.out.printf("%04d", 123);
System.out.println();
}
}
You could also make it "%0" + size + "%d" if you wanted to vary the length... though if the lengths were common I'd probably make constants like "%04d", "%012d", etc...

Categories