Java(Android): Convert signed byte to int - java

I am writing an Android App which will read data from another device, the data received is an byte array like:
byte[] data = {X,X,X,X,H,H,X,X};
The HH above is a ASCII hex representation of a signed byte. For example "0C" represent a value 12, "FB" represent value -5, "FF" is -1
I receive the HH from the data by:
byte[] HH_array = Arrays.copyOfRange(data, 4, 6);
And then change it to String:
String HH_str = new String(HH_array);
To get the HH value:
int HH_int = (Integer.parseInt(HH_str, 16));
However, here the integer value become a positive number even the original HH is negative.
I want to ask how can I change the signed byte received in the data array HH_array, and store it to a signed int?

I would like to answer my question, I have to add the following code at the end:
if((HH_int &0x80) > 0) {
HH_int = -(0x80-(HH_int &0x7f));
}
Firstly it compare the 8th bit to check whether it is a negative number. Then it convert to the value in 2's complemnt.
Thank you to a member who answered an "almost correct" answer which gave me hint to get what I want. Unfortunately he removed his answer and I forgot his name.

Use this:
byte b = 0xFF;
int i = (int)(sbyte)b;

Related

parseInt on a string of 8 bits returns a negative value when the first bit is 1

I've got a huge string of bits (with some \n in it too) that I pass as a parameter to a method, which should isolate the bits 8 by 8, and convert them all to bytes using parseInt().
Thing is, every time the substring of 8 bits starts with a 1, the resulting byte is a negative number. For example, the first substring is '10001101', and the resulting byte is -115. I can't seem to figure out why, can someone help? It works fine with other substrings.
Here's my code, if needed :
static String bitsToBytes(String geneString) {
String geneString_temp = "", sub;
for(int i = 0; i < geneString.length(); i = i+8) {
sub = geneString.substring(i, i+8);
if (sub.indexOf("\n") != -1) {
if (sub.indexOf("\n") != geneString.length())
sub = sub.substring(0, sub.indexOf("\n")) + sub.substring(sub.indexOf("\n")+1, sub.length()) + geneString.charAt(i+9);
}
byte octet = (byte) Integer.parseInt(sub, 2);
System.out.println(octet);
geneString_temp = geneString_temp + octet;
}
geneString = geneString_temp + "\n";
return geneString;
}
In Java, byte is a signed type, meaning that when the most significant bit it set to 1, the number is interpreted as negative.
This is precisely what happens when you print your byte here:
System.out.println(octet);
Since PrintStream does not have an overload of println that takes a single byte, the overload that takes an int gets called. Since octet's most significant bit is set to 1, the number gets sign-extended by replicating its sign bit into bits 9..32, resulting in printout of a negative number.
byte is a signed two's complement integer. So this is a normal behavior: the two's complement representation of a negative number has a 1 in the most-significant bit. You could think of it like a sign bit.
If you don't like this, you can use the following idiom:
System.out.println( octet & 0xFF );
This will pass the byte as an int while preventing sign extension. You'll get an output as if it were unsigned.
Java doesn't have unsigned types, so the only other thing you could do is store the numbers in a wider representation, e.g. short.
In Java, all integers are signed, and the most significant bit is the sign bit.
Because parseInt parse signed int that means it converts the binary if it begins with 0 its positive and if 1 its negative try to use parseUnsignedInt instead

Binary, hex, decimal comparison

I was playing a bit with numbers, and something interesting came upon me, which I don't quite understand.
public static void main(String[] args) {
int hexNumber = 0x7A;//decimal: 122 binary:0111 1010
int decNumber = 122;
int binNumber = 1111010;
System.out.println(hexNumber);//122
System.out.println(Integer.toString(hexNumber, 16)); //7a
System.out.println(Integer.toHexString(hexNumber)); //7a
System.out.println(Integer.toString(hexNumber, 2)); // 1111010
System.out.println(Integer.toBinaryString(hexNumber)); //1111010
System.out.println(hexNumber==binNumber);//false
System.out.println(hexNumber==decNumber);//true
System.out.println(decNumber==binNumber);//false
}
Why do I get "false" at #1 and #3? Doesn't change even if binNumber = 01111010;
Well, you can't directly store binary values in Java without any prefix.
binNumber isn't stored as the binary number 1111010; instead, it's stored as the decimal number 1111010.
This you have to store as int binNumber = Integer.parseInt("1111010", 2); or better yet int binNumber = 0b1111010;.
For octal:
int octalNo = 0177; //'0' is prefix
or
int octalNo = Integer.parseInt("0177", 8); //leading '0's are ignored
For hexadecimal:
int hexNo = 0x177; //'0x' is prefix
or
int hexNo = Integer.parseInt("0177", 16); //leading '0's are ignored
For more info, have a look at this.
You aren't creating the binary number as a binary one. You are creating it as a decimal one (base 10) that happens to only contain 0s and 1s.
To store 0111 1010 in Java 7 use the new binary literal (you can even use underscores for easier reading)
int binNumber = 0b0111_1010;
Because that's not the proper way to specify the binary number (and there is no such way in Java, apart from something like Integer.toBinaryString(122) which would give you a proper binary representation (returned as a String)).
Your number was interpreted as a "normal" decimal integer (if entered without leading 0) or as an integer in octal system (if entered with leading 0).
In Java versions before 7, you need to use this
int binNumber = Integer.parseInt("1111010", 2);
In 7 and up, you can use
int binNumber = 0b1111010;
With that change, your code works here (I get three true resuls).
The answer is clear. You have assigned to integers some diferent values.hexNumber is initialized to decimal value 122, even if the representation you use for that is hexadecimal. decNumber is initialized to decimal value 122, so when you compare hexNumber and decNumber you will get true because it's really the same value. Finally binNumber is initialized to the decimal value 1111010, so if you compare it with one of the other numbers you will get false.

How to convert a byte in binary representation into int in java

I have a String[] with byte values
String[] s = {"110","101","100","11","10","1","0"};
Looping through s, I want to get int values out of it.
I am currently using this
Byte b = new Byte(s[0]); // s[0] = 110
int result = b.intValue(); // b.intValue() is returning 110 instead of 6
From that, I am trying to get the results, {6, 5, 4, 3, 2, 1}
I am not sure of where to go from here. What can I do?
Thanks guys. Question answered.
You can use the overloaded Integer.parseInt(String s, int radix) method for such a conversion. This way you can just skip the Byte b = new Byte(s[0]); piece of code.
int result = Integer.parseInt(s[0], 2); // radix 2 for binary
You're using the Byte constructor which just takes a String and parses it as a decimal value. I think you actually want Byte.parseByte(String, int) which allows you to specify the radix:
for (String text : s) {
byte value = Byte.parseByte(text, 2);
// Use value
}
Note that I've used the primitive Byte value (as returned by Byte.parseByte) instead of the Byte wrapper (as returned by Byte.valueOf).
Of course, you could equally use Integer.parseInt or Short.parseShort instead of Byte.parseByte. Don't forget that bytes in Java are signed, so you've only got a range of [-128, 127]. In particular, you can't parse "10000000" with the code above. If you need a range of [0, 255] you might want to use short or int instead.
You can directly convert String bindery to decimal representation using Integer#parseInt() method. No need to convert to Byte then to decimal
int decimalValue = Integer.parseInt(s[0], 2);
You should be using Byte b = Byte.valueof(s[i], 2). Right now it parse the string treating it as decimal value. You should use valueOf and pass 2 as radix.
Skip the Byte step. Just parse it into an int with Integer.parseInt(String s, int radix):
int result = Integer.parseInt(s[0], 2);
The 2 specifies base 2, whereas the code you're using treats the input strings as decimal.

How to store Hex string in an Integer variable in android???

In the following code intArray[i] stores RGB values of pixels in hex format(eg:0xffff0000) .... The method hsvToRgb() gives bak an integer value of RGB (eg:15777252) but i need back the rgb value in the original hex format after changes.
The second line gives me that but its a string ....What do i do to store this string value back into the array? ... please help me.
int disco = hsvToRgb(hsv);
hexColor = String.format("0x%06X", (0xffffff & disco));
intArray[i] = Integer.valueOf(String.valueOf(disco), 16);
There's no such thing as a "hex format" integer versus a "decimal format" integer. The bit/byte representation of the value is the same. For example, the decimal value 15,777,252 is the hex value 0xF0BDE4. (You can use Google to convert: search "15777252 in hex").
You can use the disco value directly. If you want to print it out in a hex representation, use Integer.toHexString().
Regarding the format. Think of it like this ... The computer represents the value as a series of bits. By way of example, let's pick a random number and represent it using 8 bits: 01110101. Using a bit string to represent bigger numbers would get very long very quickly, so hexadecimal is often used. The hex equivalent is: 65. By convention, we usually precede the value by 0x when it's in hex. That gives us 0x65. Non-programmers tend to deal more naturally in base 10 however (rather than base 16). The same number in base 10 is 101.
You can see this with some code:
final int value = 0x65; // we can declare it in hex
final int sameValue = 101; // or in decimal
System.out.println(value); // output in base 10; prints "101"
System.out.println(Integer.toHexString(value)); // output in base 16; prints "65"
System.out.println(Integer.toBinaryString(value)); // output in base 2; prints "1100101"
System.out.println(""+(value == sameValue)); // prints "true"

Java: have integer, need it in byte in 0x00 format

I have an integer used to seed my for loop:
for(int i = 0; i < value; i++)
Within my for loop I am seeding a byte array with byte content values that increment +1. For instance new byte[]{0x00}; But the 0x00 needs to be 0x01 on the next iteration, how can I convert my value of integer i into a value of byte in the 0x00 format?
I tried things like Byte.valueOf(Integer.toHexString(i)) but this just gives me a value that looks like 0 instead of 0x00.
new byte[]{0x00}
is actually equivalent to
new byte[]{0}
The 0x00 notation is just an alternative way to write integer constants, and if the integer constant is in the range -128 to 127, then it can be used as a byte.
If you have an existing integer variable that you want to use, and its value is in the range -128 to 127, then you just have to cast it:
int i = 1;
new byte[]{(byte)i};
I think the real problem is that you are confused about number representations and text renderings of numbers. Here are some key facts that you need to understand:
The byte type is the set of integral values from -128 to +127.
All integral types use the same representation (2's complement). The difference between the different types is their ranges.
When you "see" a number, what you are seeing is a rendering of the number into a sequence of characters. There are MANY possible renderings; e.g. the number represented in memory as 00101010 (42) can be rendered as "42" or "+42" or "0x2a" or ... "forty two".
The default format for rendering a byte, short, int and long is the same; i.e. an optional minus sign followed by 1 or more decimal digits (with no zero padding). If you want to see your numbers formatted differently, then you need to do the formatting explicitly; e.g. using String.format(...).
So to pull this together, if you want the bytes to look like 0x00 and 0x01 when you output or display them, you need to format them appropriately as you output / display them. In your example code, I doubt that there is anything wrong with the numbers themselves, or with the loop you are using to populate the array.
You are confusing the string representation of the value with the value itself. A value can be represented as binary, decimal, or hex, but it is still the same value.
If you want to use your integer to initialise a byte array, you just need to cast your integer value to a byte value as follows:
arr[i] = (byte) i;
You want
new byte[]{(byte)i}
How you print this array is another matter. Look up printf in the API reference.
I would just like to note that 0 is NOT the same thing as 0x00. If i were to use:
ColorChooserOutputText.append(Integer.toHexString(list[i].getRed()));
ColorChooserOutputText.append(Integer.toHexString(list[i].getGreen()));
ColorChooserOutputText.append(Integer.toHexString(list[i].getBlue()));
and wanted to return the color, Purple it would return: ff0cc Which would be fine if I were just using Java. But if you are going between Java and something that had format specific needs ff0cc would not produce purple.. ff00cc is actually purple.
//Declare some variables.
Color HexColor = JButton1.getBackground();
String MyRValue = null;
String MyGValue = null;
String MyBValue = null;
//Get Hex Value
MyRValue = Integer.toHexString(HexColor.getRed());
MyGValue = Integer.toHexString(HexColor.getGreen());
MyBValue = Integer.toHexString(HexColor.getBlue());
//Make sure to keep both 0's
MyRValue = ("00"+MyRValue).substring(MyRValue.length());
MyGValue = ("00"+MyGValue).substring(MyGValue.length());
MyBValue = ("00"+MyBValue).substring(MyBValue.length());
//Format your HexColor to #00ff00, #000000, #ff00ee
JTextArea1.append("#");
JTextArea1.append(MyRValue+MyGValue+MyBValue);
JTextArea1.append(", ");
String.Format ("%02x") is your friend :)
http://download.oracle.com/javase/1.5.0/docs/api/java/util/Formatter.html
http://www.xinotes.org/notes/note/1195/

Categories