I need to convert decimal value like
int dec = 129;
into a byte value like
byte frame2 = (byte) 129;
but as you might already have guessed, it converts into an unexpected value. I want the byte value to be literally 129 instead of -127 (value of frame2).
How could you achieve it in Java? I would appreciate an explanation as well.
Thanks
You can't and most likely you don't need to. a byte is -128 to 127 by definition. However you can store any 256 different values in a byte if you want with encoding.
byte b = (byte) 129;
int i = b & 0xff; // == 129
or
byte b = (byte) (129 + Byte.MIN_VALUE);
int i = b - Byte.MIN_VALUE; // also 129.
I need to convert decimal value like
Stop right there. There is no such thing as a 'decimal value'. There are values, which are held in 2s-complement, and there are decimal representations.
int dec = 129;
That will be stored as 129(10), or 81(16).
into a byte value like
byte frame2 = (byte) 129;
The result of that will be -127, because bytes are signed in Java and your value sets the sign bit.
If you want to use the value as though it was 129, use (frame2 & 0xff). However it is quite likely that you don't need to do that at all.
Your question is actually about sign-extension of bytes in Java: it has nothing to do with decimals at all.
Related
I have question regarding my code here:
public class Main
{
public static void main(String[] args) {
System.out.println("Hello World\n");
int x = 36;
byte b1 = ((byte) x) & ((byte) 0xff); // it seems it is the part after &, but I have 0xff cast to byte by using (byte)0xff, so not sure where exactly the error is coming from.
System.out.println(b1);
}
}
I am not sure exactly which part is causing the error of:
incompatible types: possible lossy conversion from int to byte
This is the error message output from the program:
You appear to be confused.
There is no point in your code. taking any number, calculating that & 0xFF, and then storing it in a byte, is always a noop - it does nothing.
You additionally get an error because & inherently always produces at least an int (it'll upcast anything smaller to match), so you're trying to assign an int to a byte.
What are you trying to accomplish?
"I want to have my byte be unsigned"!
No can do. Java doesn't have unsigned bytes. A java byte is signed. Period. It can hold a value between -128 and +127. For calculation purposes, -128 and 255 are identical (they are both the bit sequence 1111 1111 - in hex, 0xFF, and they act identically under all relevant arithmetic, though it does get tricky when converting them to another numeric type int).
"I just want to store 255"!
Then use int. This is where most & 0xFF you'll ever see in java code comes from: When you have a byte value which java inherently treats as signed, but you wish to treat it as unsigned and, therefore (given that in java bytes can't do that), you want to upcast it to an int, containing the unsigned representation. This is how to do that:
int x = y & 0xFF;
Where y is any byte.
You presumably saw this somewhere and are now trying to apply it, but assigning the result of y & 0xFF to a byte doesn't mean anything. You'd assign it to an int variable, or just use it as expression in a further calculation (y & 0xFF is an int - make sure you add the appropriate parentheses, & has perhaps unexpected precedence).
int x = 36;
byte b1 = ((byte) x) & ((byte) 0xff);
Every imaginable way of this actually working would mean that b1 is... still 36.
To compute x & y where the two operands are bytes, they must first be promoted to int values. There is no & between bytes. The result is therefore of type int
That is, what you wrote is effectively evaluated as if you'd written it as the following, making explicit what the language gives you implicitly:
byte b1 = ((int) (byte) x) & ((int) (byte) 0xff);
Just do the arithmetic and then cast the result to byte.
byte b1 = (byte)(x & 0xff);
Link to Java Language Specification
Edited to add, thanks to #rzwitserloot, that masking a byte value with 0xff is however pointless. If you need the assignment from an integer to a byte, just write the cast:
byte b1 = (byte)x;
I have a problem. I receive a double val=80.22. Then I split it:
String[] arr=String.valueOf(val).split("\\.");
int[] intArr=new int[2];
intArr[0]=Integer.parseInt(arr[0]); // 80
intArr[1]=Integer.parseInt(arr[1]); // 22
Now i need to put this values into a byte[]. But I don't need the value into the byte[], I need it like this: 0x80 , 0x22.
What I have tried:
byte firstbyte = Byte.parseByte(arr[0], 16);
byte secondbyte = Byte.parseByte(arr[1], 16);
This works fine but only to the value 80, then I receive:
java.lang.NumberFormatException: Value out of range. Value:"80" Radix:16
But I don't get it. I need the number up to the value 100.
I have tried to write it into a string like string = 0x80 but I don't know how to put it into the byte[] then.
Thanks for your help!
Its hard for me to understand the question, but if you want to put a number up to the value 100 in a byte data type you just need to write:
byte firstbyte = (byte)intArr[0];
byte secondbyte = (byte)intArr[1];
Because 0x80 is an hexadecimal value and its worth to the decimal 128 which is too big for that data type.
Bytes are signed in Java. The highest value in a byte, in hexadecimal is 7F, so 80 is too big. Unfortunately there is no parseUnsignedByte.
The workaround is to use the type with the next higher range up, a short, then cast the result back to byte.
byte firstbyte = (byte) Short.parseShort(arr[0], 16);
byte secondbyte = (byte) Short.parseShort(arr[1], 16);
This will turn "80" into -128, but the byte representation is correct: 1000 0000, or 80 in hexadecimal.
Note that if the short value is out of the range of even an unsigned byte (at least 256, or "100" in hexadecimal), then this will silently truncate the value to the least significant 8 bits, i.e. 256 -> 0, 257 -> 1, etc.
byte max value is 2^7 - 1 = 127 in dec.
0x80 is hex representation of 128 in dec.
Hex counts from 0 to 9 then from A to F.
So, 80 in dec will be 0x50.
Simply avoid second parameter in Byte.parseByte() or use Byte.valueOf("80")
We have a file which contains byte array in particular format like header and then followed by data. This file is generated by another java program and then we are reading that same file through another java program in the same format in which it was written.
The program which is making that file, populates lengthOfKey as byte which is right as that's what we need as shown below.
for (Map.Entry<byte[], byte[]> entry : holder.entrySet()) {
byte typeKey = 0;
// getting the key length as byte (that's what we need to do)
byte lengthOfKey = (byte) entry.getKey().length;
byte[] actualKey = entry.getKey();
}
Now as byte can only store maximum value as 127, we are seeing for some of our record lengthOfKey is coming as negative while we read the file as shown below:
Program which is reading the file:
byte keyType = dis.readByte();
// for some record this is coming as negative. For example -74
byte lengthOfKey = dis.readByte();
Now my question is : Is there any way I can find out what was the actual length of key because of that it got converted to -74 while writing it. I mean it should be greater than 127 and that's why it got converted to -74 but what was the actual value?
I think question would be how to convert negative byte value to either short or integer? I just wanted to verify to see what was the actual length of key because of that it got converted to negative value.
If the original length from entry.getKey().length is greater than 255, then the actual length information is lost. However, if the original length was between 128 and 255, then it can be retrieved.
The narrowing conversion of casting to byte keeps only the least significant 8 bits, but the 8th bit is now interpreted as -128 instead of 128.
You can perform a bit-and operation with 0xFF, which will retain all bits, but that implicitly widens the value back to an int.
int length = lengthOfKey & 0xFF;
lengthOfKey (byte = -74): 10110110
Widening it to an int, with sign extension:
lengthOfKey (int = -74): 11111111 11111111 11111111 10110110
Masking out the last 8 bits as an int:
length (int = 182): 00000000 00000000 00000000 10110110
That will convert a negative byte back to a number between 128 and 255.
If you use Guava, it provides a number of unsigned math utilities, including UnsignedBytes.
UnsignedBytes.toInt(lengthOfKey);
Notice their implementation of toInt() is exactly what #rgettman suggests.
To convert an assumed unsigned byte to an int.
int value = (byteValue >= (byte) 0) ? (int) byteValue : 256 + (int) byteValue;
I have an integer called writePos that takes a value between [0,1023]. I need to store it in the last two bytes of a byte array called bucket. So, I figure I need to represent it as a concatenation of the array's last two bytes.
How would I go about breaking down writePos into two bytes that, when concatenated and cast into an int, produces writePos again?
How would I go about concatenating once I get it broken down into the bytes?
This would be covered high-level by a ByteBuffer.
short loc = (short) writeLocation;
byte[] bucket = ...
int idex = bucket.length - 2;
ByteBuffer buf = ByteBuffer.wrap(bucket);
buf.order(ByteOrder.LITTLE__ENDIAN); // Optional
buf.putShort(index, loc);
writeLocation = buf.getShort(index);
The order can be specified, or left to the default (BIG_ENDIAN).
The ByteBuffer wraps the original byte array, and changes to ByteBuffer effect on the byte array too.
One can use sequential writing and reading an positioning (seek), but here I use overloaded methods for immediate positioning with index.
putShort writes to the byte array, modifying two bytes, a short.
getShort reads a short from the byte array, which can be put in an int.
Explanation
A short in java is a two-byte (signed) integral number. And that is what is meant. The order is whether LITTLE_ENDIAN: least significant byte first (n % 256, n / 256) or big endian.
Bitwise operations.
To byte:
byte[] bytes = new byte[2];
// This uses a bitwise and (&) to take only the last 8 bits of i
byte[0] = (byte)(i & 0xff);
// This uses a bitwise and (&) to take the 9th to 16th bits of i
// It then uses a right shift (>>) then move them right 8 bits
byte[1] = (byte)((i & 0xff00) >> 8);from byte:
To go back the other way
// This just reverses the shift, no need for masking.
// The & here is used to handle complications coming from the sign bit that
// will otherwise be moved as the bytes are combined together and converted
// into an int
i = (byte[0] & 0xFF)+(byte[1] & 0xFF)<<8;
There is a working example here of some of the conversions that you can play around with:
http://ideone.com/eRzsun
You need to split the integer into two bytes. The high and the low byte. Following your description it's stored as bug endian in the array.
int writeLocation = 511;
byte[] bucket = new byte[10];
// range checks must be done before
// bitwise right rotation by 8 bits
bucket[8] = (byte) (writeLocation >> 8); // the high byte
bucket[9] = (byte) (writeLocation & 0xFF); // the low byte
System.out.println("bytes = " + Arrays.toString(bucket));
// convert back the integer value 511 from the two bytes
bucket[8] = 1;
bucket[9] = (byte) (0xFF);
// the high byte will bit bitwise left rotated
// the low byte will be converted into an int
// and only the last 8 bits will be added
writeLocation = (bucket[8] << 8) + (((int) bucket[9]) & 0xFF);
System.out.println("writeLocation = " + writeLocation);
I have written the following program in Java to convert long to byte.
public class LongtoByte
{
public static void main(String[] args)
{
long a=222;
byte b=(byte)(a & 0xff);
System.out.println("the value of b is" +b);
}
}
The problem is I get the result -34 for the variable b.
Please tell me how to get the correct value. I want the value in bytes only.
Java's types are signed, bytes allow numbers between −128 and +127.this is the reason you were getting −34 for 222 value
long a=121;
byte b=(byte)(a );
System.out.println("the value of b is" +b);
All integer types (including byte) are signed in Java, so if you stick 222 into a Java byte you get an overflow (resulting in the negative number you saw). If you need the range 0–255 for a integral number in Java you'll need at least a short.
However, if you're just going to write that result somewhere as a single byte you don't need to worry, as its bit pattern representation is exactly the same as 222 in an unsigned byte.
You can use the java.lang.Long class' byteValue() method:
byte b = a.byteValue();
You will have to make a Long type object as such:
Long a = new Long(222);
And as others have noted, this will return -34 due to overflow of the range that can be represented by a byte which is 8 bits.
When you print a byte it assumes a range of -128 to 127.
If you print
byte b = (byte) 222;
you should expect to get a negative number.
If you want to store the range 0 to 255 you need to convert it when you get the value out.
int i = 222;
byte[] b = { (byte) i };
int i2 = b[0] & 0xFF; // give me the original unsigned 0 to 255.
assert i == i2;
You can invent all sorts of encoding. e.g. Say you want to store numbers which are only in millions say 0 to 200 million or decimal numbers -1.00 to 1.00 in a byte. You might first think this is impossible because a byte only stores 8 bits.
// store millions.
byte b = (byte) (i / 1000000);
int i = (b & 0xff) * 1000000;
// store decimal from -1.00 to 1.00
byte b = (byte) Math.round(d * 100);
double d = b / 100.0;
public class LongtoByte
{
public static void main(String[] args)
{
long a=222;
byte b=(byte)(a);
System.out.println("the value of b is" +b);
}
}
This byte bValue = (byte) num; statement is converted into a byte format.