For an assignment I get some bytes, make some calculations on their Binary values and have to return that calculated Stuff in a Byte Array.
My Problem is now, that byte only stores up to 127, but my values can be up to 2^8-1 (11111111). I already tried to convert it to hex, but it´s of course not working either.
So, is that possible, if yes how, or is that exercise not possible like that?
If I'm understanding your question, before you perform any calculations you need to AND (&) your bytes against 255, so you'll be dealing with values from 0 to 255 instead of -128 to 127. When you assign a value higher than 127 to a byte it overflows, so 128 as a byte in java is -128, but after you AND (&) -128 against 255 you'll get +128.
// This prints 0 to 127, then -128 to -1
public static void main(String[] args) {
for (int i = 0; i <= 255; i++) {
System.out.println(((byte)i));
}
}
// Where this will print 0 to 255
public static void main(String[] args) {
for (int i = 0; i <= 255; i++) {
System.out.println(((byte)i) & 255);
}
}
Typically, in Java, this number would be represented as an int. That gives you more than enough room to store your values. If you need to represent it as a byte, for transmitting it somewhere or something like that, then you would cast it like
int i = 255;
byte b = (byte) (i & 0xff);
but in this case, it will still be negative, because byte is signed in Java.
Also, hexadecimal literals are by default of type int, as you've probably found out. So 0xff does have the value of 255 like you intend, but it's an int, not a byte.
Related
I have next method for converting to int from hex:
public static byte[] convertsHexStringToByteArray2(String hexString) {
int hexLength = hexString.length() / 2;
byte[] bytes = new byte[hexLength];
for (int i = 0; i < hexLength; i++) {
int hex = Integer.parseInt(hexString.substring(2 * i, 2 * i + 2), 16);
bytes[i] = (byte) hex;
}
return bytes;
}
when I use it for "80" hex string I get strange, not expected result:
public static void main(String[] args) {
System.out.println(Arrays.toString(convertsHexStringToByteArray2("80"))); // gives -128
System.out.println(Integer.toHexString(-128));
System.out.println(Integer.toHexString(128));
}
the output:
[-128]
ffffff80
80
I expect that "80" will be 128. What is wrong with my method?
I have next method for converting to int from hex
The method you posted converts a hex String to a byte array, and not to an int. That's why it is messing with its sign.
Converting from hex to int is easy:
Integer.parseInt("80", 16)
$1 ==> 128
But if you want to get a byte array for further processing by just casting:
(byte) Integer.parseInt("80", 16)
$2 ==> -128
It "changes" its sign. For further information on primitives and signed variable types take a look at Primitive Data Types, where it says:
The byte data type is an 8-bit signed two's complement integer. It has a minimum value of -128 and a maximum value of 127 (inclusive). The byte data type can be useful for saving memory in large arrays, where the memory savings actually matters. They can also be used in place of int where their limits help to clarify your code; the fact that a variable's range is limited can serve as a form of documentation.
One could easily invert the sign by just increasing the value to convert:
(byte) Integer.parseInt("80", 16) & 0xFF
$3 ==> 128
That gets you a byte with the value you expect. Technically that result isn't correct and you must to switch the sign again, if you want to get an int or a hex string back again. I'd suggest you to don't use a byte array if you only want to convert between hex and dec.
A byte in Java stores numbers from -128 to 127. 80 in hex is 128 as an integer, which is too large to be stored in a byte. So, the value wraps around. Use a different type to store your value (such as a short).
I have long value, which i want to convert ot byte array. I use this function
public static byte[] longToByteArray(long value) {
byte[] result = new byte[8];
for(int i = 0; i < 8; i++) {
result[i] = (byte)(value & 0xFF);
System.out.println(result[i]);
System.out.println(Integer.toBinaryString(result[i]));
value >>>= 8;
}
return result;
}
and output data looks like
18
10010
-12
11111111111111111111111111110100
88
1011000
83
1010011
0
0
0
0
0
0
0
0
Why i have too much 1 in binary view of -12, and how can i get it like
11110100
That's because Integer.toBinaryString(result[i]) converts your byte to int (32 bits), and also, bytes are represented from -128 to 127, so values grater than 127 are being represented as negative numbers; hence, your byte ends up being a negative int. to solve it you can change this line:
System.out.println(Integer.toBinaryString(result[i]));
for this one:
System.out.println(Integer.toBinaryString(result[i] & 0xFF));
Your -12 is coming out as 11111111111111111111111111110100 because it is a negative number encoded in 2's complement format using all 32-bits available to it as it is being parsed as an integer.
If you only want the final 8 bits, you'll probably have to format it like that. Check this answer: How to convert a byte to its binary string representation
The reason is that even though you do (byte)(value & 0xFF) when you call Integer.toBinaryString it is being converted back to a 32 bit integer and you are getting proper output for -12 integer.
One simple solution is to convert negative byte values (-128 to -1) to be positive unsigned byte values (128 to 255). This is done simply by testing for negative and adding 256, like such:
int b = (int)(value & 0xFF);
if (b<0) {
b = b + 256;
}
This is done in an integer data type, but the resulting value is 0..255 which is appropriate for an unsigned byte. So now, it turns out, instead of -12 you will have 244 but it turns out that the binary representation of 244 is the same as an 8-bit version of -12. Try it out!
you can use JBBP
byte [] packed = JBBPOut.BeginBin().Long(aLongValue).End().toByteArray();
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);
}
There is 2-bytes array:
private byte[] mData;
and method:
public void setWord(final short pData) {
mData[0] = (byte) (pData >>> 8);
mData[1] = (byte) (pData);
}
I wrote the simple test:
public void testWord() {
Word word = new Word();
word.setWord((short) 0x3FFF);
Assert.assertEquals(0x3F, word.getByte(0));
Assert.assertEquals(0xFF, word.getByte(1));
}
The second assert fails with message "Expected 255, but was -1".
I know, that 0xFF signed short is, in fact, -1, but why JUnit thinks, that they are not equal? And, what is the correct way to implement such classes?
Java does not support unsigned types, so in order for a value to be 255, it must not be a signed byte, which is incapable of holding the value of 255. The 0xFF constant value will be taken as a signed int, and for the comparison, the byte value 0xFF will be converted to an int at -1 as well.
You need to type cast the literal 0xFF to be a byte. Change the assert to be Assert.assertEquals((byte)0xFF, word.getByte(1)); Then the left hand side will evaluate to -1 as well as the right.
The comment from biziclop is correct.
Any Integer number you specify in your code is considered an Integer unless marked otherwise.
Change your assertion to:
Assert.assertEquals((byte)0xFF, word.getByte(1))
And it should pass fine - as the first two bytes of the integer will be considered as a
byte.
Bitwize speeking - basically when you write 0xFF the compiler interprets it as 0x000000FF which is 255.
You want 0xFFFFFFFF which is -1.
Casting to byte is the correct solution here
There are no unsigned types in java.
0xFF is the int 255 and casted to byte overflows to -1.
I usually work with bytes as integers if I want them unsigned. I usually do that this way:
int b1 = getByte() & 0xFF;
For example:
byte byte1 = 0xFF; // 255 = -1
byte byte2 = 0xFE; // 254 = -2
int int1 = (byte1 & 0xFF) + (byte1 & 0xFF); // 255 + 254 = 509
I know Java doesn't allow unsigned types, so I was wondering how it casts an integer to a byte. Say I have an integer a with a value of 255 and I cast the integer to a byte. Is the value represented in the byte 11111111? In other words, is the value treated more as a signed 8 bit integer, or does it just directly copy the last 8 bits of the integer?
This is called a narrowing primitive conversion. According to the spec:
A narrowing conversion of a signed integer to an integral type T simply discards all but the n lowest order bits, where n is the number of bits used to represent type T. In addition to a possible loss of information about the magnitude of the numeric value, this may cause the sign of the resulting value to differ from the sign of the input value.
So it's the second option you listed (directly copying the last 8 bits).
I am unsure from your question whether or not you are aware of how signed integral values are represented, so just to be safe I'll point out that the byte value 1111 1111 is equal to -1 in the two's complement system (which Java uses).
int i = 255;
byte b = (byte)i;
So the value of be in hex is 0xFF but the decimal value will be -1.
int i = 0xff00;
byte b = (byte)i;
The value of b now is 0x00. This shows that java takes the last byte of the integer. ie. the last 8 bits but this is signed.
or does it just directly copy the last
8 bits of the integer
yes, this is the way this casting works
The following fragment casts an int to a byte. If the integer’s value is larger than the range of a byte, it will be reduced modulo (the remainder of an integer division by the) byte’s range.
int a;
byte b;
// …
b = (byte) a;
Just a thought on what is said: Always mask your integer when converting to bytes with 0xFF (for ints). (Assuming myInt was assigned values from 0 to 255).
e.g.
char myByte = (char)(myInt & 0xFF);
why? if myInt is bigger than 255, just typecasting to byte returns a negative value (2's complement) which you don't want.
Byte is 8 bit. 8 bit can represent 256 numbers.(2 raise to 8=256)
Now first bit is used for sign. [if positive then first bit=0, if negative first bit= 1]
let's say you want to convert integer 1099 to byte. just devide 1099 by 256. remainder is your byte representation of int
examples
1099/256 => remainder= 75
-1099/256 =>remainder=-75
2049/256 => remainder= 1
reason why? look at this image http://i.stack.imgur.com/FYwqr.png
According to my understanding, you meant
Integer i=new Integer(2);
byte b=i; //will not work
final int i=2;
byte b=i; //fine
At last
Byte b=new Byte(2);
int a=b; //fine
for (int i=0; i <= 255; i++) {
byte b = (byte) i; // cast int values 0 to 255 to corresponding byte values
int neg = b; // neg will take on values 0..127, -128, -127, ..., -1
int pos = (int) (b & 0xFF); // pos will take on values 0..255
}
The conversion of a byte that contains a value bigger than 127 (i.e,. values 0x80 through 0xFF) to an int results in sign extension of the high-order bit of the byte value (i.e., bit 0x80). To remove the 'extra' one bits, use x & 0xFF; this forces bits higher than 0x80 (i.e., bits 0x100, 0x200, 0x400, ...) to zero but leaves the lower 8 bits as is.
You can also write these; they are all equivalent:
int pos = ((int) b) & 0xFF; // convert b to int first, then strip high bits
int pos = b & 0xFF; // done as int arithmetic -- the cast is not needed
Java automatically 'promotes' integer types whose size (in # of bits) is smaller than int to an int value when doing arithmetic. This is done to provide a more deterministic result (than say C, which is less constrained in its specification).
You may want to have a look at this question on casting a 'short'.