Issues with OR-ing with bytes in Java? - java

Let's say I have the following code in java
byte t = (byte) 0b10001000;
byte z = 0b00000000;
z = (byte) (t|z);
You'd think the output would be 10001000, however it ends up being -1111000 in String representation, the - sign being the first 1 of course, making it 11111000. If I do the same code but with the last bit in z as a 1, e.g. 00000001, and I perform the same operation, I get -1110111, or 11110111. I figure this is due to some conversion issue with the negatively signed byte t. Is there any way to avoid this? Is there any way to have 10000000 work the same in an OR operation as 01000000?

Java doesn't have unsigned types, so when you use binary notaion and set the sign bit things will not go as you expect ;-)
To emulate an unsigned type you need to work in the next size up.

Related

Why is AS3 right bit shift different than the same thing in Java?

Hard to explain without some code.. so
var junk:uint = uint(4294280300);
trace(junk.toString(2)); // returns 11111111111101011000010001101100
junk = junk >> 8;
trace(junk.toString(2)); // returns 11111111111111111111010110000100
and here is the Java part
long junk = 4294280300L;
System.out.println(Long.toBinaryString(junk)); // returns 11111111111101011000010001101100
junk = junk >> 8;
System.out.println(Long.toBinaryString(junk)); // returns 111111111111010110000100
What am I doing wrong? How can I achieve the same result in Java? I have tried using >>> instead of >> but it doesn't seem to work.
I don't know ActionScript at all, but it's for sure due to differences in the internal representation of numbers.
The type uint of ActionScript seem indeed to be an unsigned integer coded on 32 bits.
Additionally, the number appear to be converted into a signed integer before the right shift operation is performed. This counter-intuitive behavior explains the result.
You don't have this problem in Java because long is an integer number coded on 64 bits, and the value 4294280300 perfectly fits into 64 bits.
You would have observed the same result as in ActionScript if you have had used an int instead of a long.
Let's look at what JavaScript does to better understand what appears to happen in ActionScript: JavaScript stores all numbers as double floating-point and you are sure to not lose precision on integers that can fit in 53 bits.
Trying with the same value, see that you get the same result as in ActionScript if you use >>, but the same as Java if you use >>>.
ON JavaScript side, it appears that >> a.k.a arithmetic shift converts first the value to 32-bit signed integer, while it doesn's with >>> a.k.a logical shift.
That's weird, and wouldn't really surprising that ActionScript does something similar.
Interestingly, python has no >>>operator, always does an arithmetic shift, and seems to work even beyond 64 bits.
Given the popularity of this question
or this one, >> vs. >>> is a common source of confusion in languages where the two operators exist.

Get least significant bytes from an integer

I need to sum all data bytes in ByteArrayOutputStream, adding +1 to the result and taking the 2 least significant bytes.
int checksum = 1;
for(byte b : byteOutputStream.toByteArray()) {
checksum += b;
}
Any input on taking the 2 least significant bytes would be helpful. Java 8 is used in the environment.
If you really mean least significant bytes then:
checksum & 0xFFFF
If you meant that you want to take least significant bits from checksum, then:
checksum & 0x3
Add
checksum &= 0x0000ffff;
That will zero out everything to the left of the 2 least significant bytes.
Your question is a bit underspecified. You didn’t say neither, what you want to do with these two bytes nor how you want to store them (which depends on what you want to do).
To get to individual bytes, you can use
byte lowest = (byte)checksum, semiLowest=(byte)(checksum>>8);
In case you want to store them in a single integer variable, you have to decide, how these bytes are to be interpreted numerically, i.e signed or unsigned.
If you want a signed interpretation, the operation is as simple as
short lowest2bytes = (short)checksum;
If you want an unsigned interpretation, there’s the obstacle that Java has no dedicated type for that. There is a 2 byte sized unsigned type (char), but using it for numerical values can cause confusion when other code tries to interpret it as character value (i.e. when printing). So in that case, the best solution is to use an int variable again and only initialize it with the unsigned char value:
int lowest2bytes = (char)checksum;
Note that this is semantically equivalent to
int lowest2bytes = checksum&0xffff;
seen in other solutions.

How do I convert a Hex value (example: 0xD1) to a unsigned Byte in Java?

I am trying to take hex values and move them into a byte array. When I do this they are not converted how I need them to be. Most of them are converted to negative numbers. For example, after the execution of the C# code "baCommandPDI[0] = 0xD1;", the value of baCommandPDI[0] is "209". This is what I need. No matter what I try in Java, the value is "-47". I need it to be "209" in the byte array, because this byte array is sent out over TCP/IP to some external hardware. The external hardware cannot interpret -47 as 209. It must be 209. I have tried the following code:
int intTemp = 0xD1; After this line is executed the value of intTemp is 209, great!
int intHexValue = 0xD1 & 0xFF; After this line is executed the value of intHexValue is still 209, I don't understand how, but it ia what it is.
baCommand[0] = (byte) intHexValue; After this line is executed the value of baCommand[0] is -47, bad. This is not what I want. Everytime it converts the value to a byte it makes it signed.
Is there any other way I can do this? Can I use 11010001 and some how assign that value to a byte without making it negative?
In Java, bytes are always signed. But like an unsigned byte in another language, 8 bits are still used. The byte representations for 209 (unsigned) and -47 are the same.
1101 0001
The only difference is how Java interprets the most significant bit -- -128 vs. 128 in an unsigned type. The difference is 256, which is the difference between 209 and -47. You can send the value as is, because the bit values are the same, only the interpretations of this bit pattern are different.
If you would like to convert the value -47 to 209 to convince yourself in Java, you can promote the type to a longer primitive type and mask out the last 8 bits. This line will do this is one line, so you can debug and see that the bits are the same and that the unsigned version is equivalent.
int test = baCommandPDI[0] & 0xFF;
Printing/debugging test will let you see the value 209.
Java does not have a concept of unsigned bytes.
To get 209 from 0xD1, try:
0xD1 & 0xFF;

Is this statement correct in java?

I would like to do a data transfer between two computers using datagram socket.Iam using the following line this way :
host=InetAddress.getByAddress("mypc",new byte[]{192,168,1,110});
but when i use the above statement i get this error :"Possible loss of precision"
So i cast the int to bytes this way :
InetAddress.getByAddress("mypc",new byte[]{(byte)192,(byte)168,(byte)1,(byte)110});
Would the above statement work now ???
If you already have it in a string, just use getByName():
InetAddress host = InetAddress.getByName("192.168.1.110");
Using bytes is cluttered, and possibly dangerous (due to signed byts used in Java). Stick with Strings if you can.
There's no problem casting the positive integer literals into byte values, even if they overflow.
The InetAddress.getByAddress() function copes perfectly well with the fact that values exceeding 127 will be converted into negative numbers.
The only thing you need to watch out for is converting the signed bytes back into integers if you subsequently want to display them. This works fine:
byte b = (byte)192;
System.out.println(b); // outputs "-64"
int i = (b & 0xff);
System.out.println(i); // outputs "192"
java bytes are signed (stupid, I know) so larger than 127 is not possible.
See alnitaks' response for a more complete (and later:) answer.
It might not, cos the max value for a byte is 127 and beyond that it would rollover to the negative -64 for 192, -88 for 168 and so on...

What is the best way to work around the fact that ALL Java bytes are signed?

In Java, there is no such thing as an unsigned byte.
Working with some low level code, occasionally you need to work with bytes that have unsigned values greater than 128, which causes Java to interpret them as a negative number due to the MSB being used for sign.
What's a good way to work around this? (Saying don't use Java is not an option)
It is actually possible to get rid of the if statement and the addition if you do it like this.
byte[] foobar = ..;
int value = (foobar[10] & 0xff);
This way Java doesn't interpret the byte as a negative number and flip the sign bit on the integer also.
When reading any single value from the array copy it into something like a short or an int and manually convert the negative number into the positive value it should be.
byte[] foobar = ..;
int value = foobar[10];
if (value < 0) value += 256 // Patch up the 'falsely' negative value
You can do a similar conversion when writing into the array.
Using ints is generally better than using shorts because java uses 32-bit values internally anyway (Even for bytes, unless in an array) so using ints will avoid unnecessary conversion to/from short values in the bytecode.
Probably your best bet is to use an integer rather than a byte. It has the room to allow for numbers greater than 128 without the overhead of having to create a special object to replace byte.
This is also suggested by people smarter than me (everybody)
http://www.darksleep.com/player/JavaAndUnsignedTypes.html
http://www.jguru.com/faq/view.jsp?EID=13647
The best way to do bit manipulation/unsigned bytes is through using ints. Even though they are signed they have plenty of spare bits (32 total) to treat as an unsigned byte. Also, all of the mathematical operators will convert smaller fixed precision numbers to int. Example:
short a = 1s;
short b = 2s;
int c = a + b; // the result is up-converted
short small = (short)c; // must cast to get it back to short
Because of this it is best to just stick with integer and mask it to get the bits that you are interested in. Example:
int a = 32;
int b = 128;
int foo = (a + b) | 255;
Here is some more info on Java primitive types http://mindprod.com/jgloss/primitive.html
One last trivial note, there is one unsigned fixed precision number in Java. That is the char primitive.
I know this is a very late response, but I came across this thread when trying to do the exact same thing. The issue is simply trying to determine if a Java byte is >127.
The simple solution is:
if((val & (byte)0x80) != 0) { ... }
If the real issue is >128 instead, just adding another condition to that if-statement will do the trick.
I guess you could just use a short to store them. Not very efficient, but really the only option besides some herculean effort that I have seen.

Categories

Resources