I'm having a small error in my code that I can not for the life of me figure out.
I have an array of strings that are representations of binary data (after converting them from hex) for example:
one index is 1011 and another is 11100. I go through the array and pad each index with 0's so that each index is eight bytes. When I try to convert these representations into actual bytes I get an error when I try to parse '11111111' The error I get is:
java.lang.NumberFormatException: Value out of range. Value:"11111111" Radix:2
Here is a snippet:
String source = a.get("image block");
int val;
byte imageData[] = new byte[source.length()/2];
try {
f.createNewFile();
FileOutputStream output = new FileOutputStream(f);
for (int i=0; i<source.length(); i+=2) {
val = Integer.parseInt(source.substring(i, i+2), 16);
String temp = Integer.toBinaryString(val);
while (temp.length() != 8) {
temp = "0" + temp;
}
imageData[i/2] = Byte.parseByte(temp, 2);
}
Isn't the problem here that byte is a signed type, therefore its valid values are -128...127? If you parse it as an int (Using Integer.parseInt()), it should work.
By the way, you don't have to pad the number with zeroes either.
Once you parsed your binary string into an int, you can cast it to a byte, but the value will still be treated as signed, so binary 11111111 will become int 255 first, then byte -1 after the cast.
Well, eight one's is 255, and according to java.lang.Byte, the MAX_VALUE is 2^7 - 1 or positive 127.
So your code will fail because you number is too large. The first bit is reserved for the positive and negative sign.
according to parseByte
byte's only allow numbers in the range of -128 to 127. I would use an int instead, which holds numbers in the range of -2.1 billion to 2.1 billion.
Related
I am putting different binary numbers into a byte array. One of the numbers are: 10001101010010010000000000001000 this number is giving me a NumberFormatException on the line where I try to parse it, obviously because it's too big. See code below where string is the binary number.
int number = Integer.parseInt(string, 2);
ByteBuffer bytes = ByteBuffer.allocate(4).putInt(number);
byte[] byteInstruction = bytes.array();
What I want is to put the numbers in my byte array but as they are 32-bit numbers I don't want to take up more than 4 bytes in my array. When I use long to parse it works but then I take up 8 spaces in my byte array.
long number = Long.parseLong(string, 2);
ByteBuffer bytes = ByteBuffer.allocate(8).putLong(number);
byte[] byteInstruction = bytes.array();
If I print out the array later I get this:
[0, 0, 0, 0, -115, 73, 0, 8]
where we can see that there are 4 spots free. How can I solve this? How did I mess up?
All help is appreciated.
Your input string "10001101010010010000000000001000" represents value that is too big for signed Integer. Integer.MAX_VALUE = 2147483647 and the input string you've passed has a value of 2370371592.
The Integer.parseInt does not interpret the leading 1 at position 32 from right as sign. If you would like parse a negative value it would have to be preceded with - sign.
See this answer for more through explanation.
If you expect the input "10001101010010010000000000001000" to in fact mean "-0001101010010010000000000001000" just replace the first character with +/- depending on the value of 32 bit from right.
Alternatively if you would like to treat the binary string in Two's complement compatible way you can use approach from this answer:
int msb = Integer.parseInt("1000110101001001", 2);
int lsb = Integer.parseInt("0000000000001000", 2);
int result = msb<<16 | lsb;
I have a small data set in HexaDecimal Representation -
byte[] bb = new byte[] { (byte)0x7D, (byte)0x44, (byte)0xCC };
To understand how the values are coming in Decimal Representation, I did the following -
Log.i("DECIMAL VALUE of 7D>>", buf[i] + "");
Log.i("DECIMAL VALUE of 44>>", buf[i+1] + "");
Log.i("DECIMAL VALUE of CC>>", buf[i+2] + "");
And what it printed was -
DECIMAL VALUE of 7D>> 125
DECIMAL VALUE of 44>> 68
DECIMAL VALUE of CC>> -52
Looking into the site -
http://hextodecimal.com/index.php?hex=CC
The Decimal Representation of byte CC is 204.
In my application I am getting Index Out Of Bounds Exception just because index at -52 doesn't exist in the bounds.
So how is this byte coming negative and what is the clear solution.
Bytes in Java are signed i.e. they range from -128 to 127. If you want to represent the number 204, use an int.
int[] bb = new int[] { 0x7D, 0x44, 0xCC };
If you really want to store the data as bytes, you can convert it to unsigned where you use it to index in an array.
yourArray[bb[1] && 0xFF]
See the following question: How to Convert Int to Unsigned Byte and Back
I'm reading a value from the screen in Android and try to convert it to a byte[] to send it over Bluetooth but every time I it takes 128 from the screen, it converts it to -128 in the byte[] and than I don't get anything on the other side..What is the problem..Why is it giving negative number?..
This is the convert code :
ByteBuffer.allocate(4).putInt(yourInt).array();
EDIT : On the other side I have to transform the byte[] to String.
And another problem..If I lower the number in the allocate() I get a BufferOverflowException even though I use only 1 position in the array. Why?
EDIT 2 : I'm working with 8bit numbers (0-255)
public static void main(String[] args) {
byte[] num = BigInteger.valueOf(-2147483648).toByteArray();
System.out.println(new BigInteger(num).intValue());
}
if you want to transfer only one byte, valued 0-255, then
public static void main(String[] args) {
for(int i=0; i<=255; i++){
byte a = (byte) i;
byte[] num = new byte [] {(byte) a};
System.out.println(num[0] + " : " + i + " : " + ((256+num[0]) % 256));
}
}
The second code will convert a byte variable to equal integer output.
The reason the code is doing this is because your integer (128) looks like
1000000 in binary with a bunch of leading zeroes. Since all Java primitives are signed, the leading bit is 0 and this comes out OK. However, when you convert to bytes the leading bit gets interpreted as the sign bit, so the last byte is interpreted as negative.
The documentation is also pretty clear that putInt() writes all 4 bytes of the integer to the buffer, instead of only the bytes which are "used".
You are seeing the correct values in the ByteBuffer. The last byte of the buffer has the byte value 0x80, which if you sign extend to a longer int value APPEARS as -128 when displaying in a dumb terminal.
BYTE VALUES
1000 0000
This hight bit typically designates a negative number in signed byte/short/int systems.
If you convert this signed byte to a larger type like an int by just prepending 1 bits, you would see this:
1111 1111 1111 1111 1111 1111 1000 0000
Which indicates -128 as a signed int.
I have binary string String A = "1000000110101110". I want to convert this string into byte array of length 2 in java
I have taken the help of this link
I have tried to convert it into byte by various ways
I have converted that string into decimal first and then apply the code to store into the byte array
int aInt = Integer.parseInt(A, 2);
byte[] xByte = new byte[2];
xByte[0] = (byte) ((aInt >> 8) & 0XFF);
xByte[1] = (byte) (aInt & 0XFF);
System.arraycopy(xByte, 0, record, 0,
xByte.length);
But the values get store into the byte array are negative
xByte[0] :-127
xByte[1] :-82
Which are wrong values.
2.I have also tried using
byte[] xByte = ByteBuffer.allocate(2).order(ByteOrder.BIG_ENDIAN).putInt(aInt).array();
But it throws the exception at the above line like
java.nio.Buffer.nextPutIndex(Buffer.java:519) at
java.nio.HeapByteBuffer.putInt(HeapByteBuffer.java:366) at
org.com.app.convert.generateTemplate(convert.java:266)
What should i do now to convert the binary string to byte array of 2 bytes?Is there any inbuilt function in java to get the byte array
The answer you are getting
xByte[0] :-127
xByte[1] :-82
is right.
This is called 2's compliment Represantation.
1st bit is used as signed bit.
0 for +ve
1 for -ve
if 1st bit is 0 than it calculates as regular.
but if 1st bit is 1 than it deduct the values of 7 bit from 128 and what ever the answer is presented in -ve form.
In your case
1st value is10000001
so 1(1st bit) for -ve and 128 - 1(last seven bits) = 127
so value is -127
For more detail read 2's complement representation.
Use putShort for putting a two byte value. int has four bytes.
// big endian is the default order
byte[] xByte = ByteBuffer.allocate(2).putShort((short)aInt).array();
By the way, your first attempt is perfect. You can’t change the negative sign of the bytes as the most significant bit of these bytes is set. That’s always interpreted as negative value.
10000001₂ == -127
10101110₂ == -82
try this
String s = "1000000110101110";
int i = Integer.parseInt(s, 2);
byte[] a = {(byte) ( i >> 8), (byte) i};
System.out.println(Arrays.toString(a));
System.out.print(Integer.toBinaryString(0xFF & a[0]) + " " + Integer.toBinaryString(0xFF & a[1]));
output
[-127, -82]
10000001 10101110
that is -127 == 0xb10000001 and -82 == 0xb10101110
Bytes are signed 8 bit integers. As such your result is completely correct.
That is: 01111111 is 127, but 10000000 is -128. If you want to get numbers in 0-255 range you need to use a bigger variable type like short.
You can print byte as unsigned like this:
public static String toString(byte b) {
return String.valueOf(((short)b) & 0xFF);
}
It seems I have a two's complement issue with Java's BigInteger.
I have a 64-bit integer where only the msb and the second msb are set to 1, the rest is 0.
In decimal this comes up to: -4611686018427387904
The Java side of my application receives this decimal number as a string, and converts it to BigInteger like so:
BigInteger bi = new BigInteger("-4611686018427387904", 10);
Then, it needs to display this number both in binary and hex forms.
I tried to use:
String bin = bi.toString(2);
String hex = bi.toString(16);
but I'm getting:
-100000000000000000000000000000000000000000000000000000000000000
-4000000000000000
whereas I expect to get:
1100000000000000000000000000000000000000000000000000000000000000
c000000000000000
Any tips?
Number always fits in 64 bits:
If your number always fits in 64 bits you can put it in a long and then print the bits / hex digits.
long l = bi.longValue();
String bin = Long.toBinaryString(l);
String hex = Long.toHexString(l);
System.out.println(bin);
System.out.println(hex);
Number may not always fit in 64 bits:
If the number does not always fit in 64 bits, you'll have to solve it "manually". To convert a number to it's two's complement representation you do the following:
If number is positive, do nothing
If number is negative:
Convert it to its absolute value
Complement the bits
Add 1
For a BigInteger the conversion looks as follows:
if (bi.compareTo(BigInteger.ZERO) < 0)
bi = bi.abs().not().add(BigInteger.ONE);
If you print it using bi.toString(2) you'll still get the sign character, instead of a leading 1. This can be solved by simply appending .replace('-', '1') to the string.
There is a BigInteger.toByteArray() method, that returns two's complement representation of BigInteger as a byte[]. All you need is to print that array in hex or binary form:
byte[] bs = bi.toByteArray();
for (byte b: bs) {
System.out.print(String.format("%02X", 0xff & b));
}
The binary number 1100000000000000000000000000000000000000000000000000000000000000 is definitely a positive number, right. It's equal to 2^63 + 2^62.
I don't see why you'd expect a negative number to become positive when you convert to base 2 or base 16.
You are confusing the base n representation with the internal representation of numbers.
If the number is 64 bits or less, then the simple way to solve this is to convert to a long and then use Long.toHexString().
what you mean?
Do you want to get Two's complement?
if you mean that, maybe i can give you an example
import java.util.*;
public class TestBina{
static void printBinaryInt(int i){
System.out.println("int:"+i+",binary:");
System.out.print(" ");
for(int j=31;j>=0;j--)
if(((1<<j)&i)!=0)
System.out.print("1");
else
System.out.print("0");
System.out.println();
}
public static void main(String [] args){
Random rand = new Random();
int i = rand.nextInt();
int j = rand.nextInt();
printBinaryInt(i);
printBinaryInt(j);
printBinaryInt(10);
printBinaryInt(-10);
}
}