Bitwise AND operation with a signed byte - java

Here is the code:
int i = 200;
byte b = (byte) 200;
System.out.println(b);
System.out.println((short) (b));
System.out.println((b & 0xff));
System.out.println((short) (b & 0xff));
Here is the output:
-56
-56
200
200
Bitwise AND with 0xff shouldn't have changed anything in b, but apparently it does have an effect, why?

It has an effect because 200 is beyond the maximum possible (signed) byte, 127. The value is already assigned -56 because of this overflow. The most significant byte, worth -128, is set.
11001000
The first 2 output statements show -56 because of this, and the fact that casting to a short will perform sign extension to preserve negative values.
When you perform & 0xff, 2 things happen. First, the value is promoted to an int, with sign extension.
11111111 11111111 11111111 11001000
Then, the bit-and is performed, keeping only the last 8 bits. Here, the 8th bit is no longer -128, but 128, so 200 is restored.
00000000 00000000 00000000 11001000
This occurs whether the value is casted to a short or not; a short has 16 bits and can easily represent 200.
00000000 11001000

Java byte is a signed type. That is why you see a negative number when you print it: 200, or 0xC8, is above the largest positive number representable by byte, so it gets interpreted as a negative byte.
However, 0xff constant is an int. When you perform arithmetic and bitwise logic operations on a byte and an int*, the result becomes an int. That is why you see 200 printed in the second set of examples: (b & 0xff) produces an integer 200, which remains 200 after shrinking conversion to short, because 200 fits into a short without becoming negative.
* or another byte, for that matter; Java standard specifies a list of conversions that get applied depending on operand types.

working with different integer types is a mine field.
for example, what's going on here?
byte b = (byte) 200;
it's actually equivalent to
int i = 200;
byte b = (byte)i;
and the narrowing cast (byte) simply takes the lowest 8 bits of the int value.

Related

Java convert from signed to unsigned in a single byte [duplicate]

I am trying to convert a signed byte in unsigned. The problem is the data I am receiving is unsigned and Java does not support unsigned byte, so when it reads the data it treats it as signed.
I tried it to convert it by the following solution I got from Stack Overflow.
public static int unsignedToBytes(byte a)
{
int b = a & 0xFF;
return b;
}
But when again it's converted in byte, I get the same signed data. I am trying to use this data as a parameter to a function of Java that accepts only a byte as parameter, so I can't use any other data type. How can I fix this problem?
The fact that primitives are signed in Java is irrelevant to how they're represented in memory / transit - a byte is merely 8 bits and whether you interpret that as a signed range or not is up to you. There is no magic flag to say "this is signed" or "this is unsigned".
As primitives are signed the Java compiler will prevent you from assigning a value higher than +127 to a byte (or lower than -128). However, there's nothing to stop you downcasting an int (or short) in order to achieve this:
int i = 200; // 0000 0000 0000 0000 0000 0000 1100 1000 (200)
byte b = (byte) 200; // 1100 1000 (-56 by Java specification, 200 by convention)
/*
* Will print a negative int -56 because upcasting byte to int does
* so called "sign extension" which yields those bits:
* 1111 1111 1111 1111 1111 1111 1100 1000 (-56)
*
* But you could still choose to interpret this as +200.
*/
System.out.println(b); // "-56"
/*
* Will print a positive int 200 because bitwise AND with 0xFF will
* zero all the 24 most significant bits that:
* a) were added during upcasting to int which took place silently
* just before evaluating the bitwise AND operator.
* So the `b & 0xFF` is equivalent with `((int) b) & 0xFF`.
* b) were set to 1s because of "sign extension" during the upcasting
*
* 1111 1111 1111 1111 1111 1111 1100 1000 (the int)
* &
* 0000 0000 0000 0000 0000 0000 1111 1111 (the 0xFF)
* =======================================
* 0000 0000 0000 0000 0000 0000 1100 1000 (200)
*/
System.out.println(b & 0xFF); // "200"
/*
* You would typically do this *within* the method that expected an
* unsigned byte and the advantage is you apply `0xFF` only once
* and than you use the `unsignedByte` variable in all your bitwise
* operations.
*
* You could use any integer type longer than `byte` for the `unsignedByte` variable,
* i.e. `short`, `int`, `long` and even `char`, but during bitwise operations
* it would get casted to `int` anyway.
*/
void printUnsignedByte(byte b) {
int unsignedByte = b & 0xFF;
System.out.println(unsignedByte); // "200"
}
I'm not sure I understand your question.
I just tried this and for byte -12 (signed value) it returned integer 244 (equivalent to unsigned byte value but typed as an int):
public static int unsignedToBytes(byte b) {
return b & 0xFF;
}
public static void main(String[] args) {
System.out.println(unsignedToBytes((byte) -12));
}
Is it what you want to do?
Java does not allow to express 244 as a byte value, as would C. To express positive integers above Byte.MAX_VALUE (127) you have to use a different integral type, like short, int or long.
Complete guide for working with unsigned bytes in Java:
Unsigned byte in Java
(Source for this answer.)
The Java Language does not provide anything like the unsigned keyword. A byte according to the language spec represents a value between −128 - 127. For instance, if a byte is cast to an int Java will interpret the first bit as the sign and use sign extension.
That being said, nothing prevents you from viewing a byte simply as 8 bits and interpret those bits as a value between 0 and 255. Just keep in mind that there's nothing you can do to force your interpretation upon someone else's method. If a method accepts a byte, then that method accepts a value between −128 and 127 unless explicitly stated otherwise.
Here are a couple of useful conversions / manipulations for your convenience:
Conversions to / from int
// From int to unsigned byte
int i = 200; // some value between 0 and 255
byte b = (byte) i; // 8 bits representing that value
// From unsigned byte to int
byte b = 123; // 8 bits representing a value between 0 and 255
int i = b & 0xFF; // an int representing the same value
(Or, if you're on Java 8+, use Byte.toUnsignedInt.)
Parsing / formatting
Best way is to use the above conversions:
// Parse an unsigned byte
byte b = (byte) Integer.parseInt("200");
// Print an unsigned byte
System.out.println("Value of my unsigned byte: " + (b & 0xFF));
Arithmetics
The 2-complement representation "just works" for addition, subtraction and multiplication:
// two unsigned bytes
byte b1 = (byte) 200;
byte b2 = (byte) 15;
byte sum = (byte) (b1 + b2); // 215
byte diff = (byte) (b1 - b2); // 185
byte prod = (byte) (b2 * b2); // 225
Division requires manual conversion of operands:
byte ratio = (byte) ((b1 & 0xFF) / (b2 & 0xFF));
There are no primitive unsigned bytes in Java. The usual thing is to cast it to bigger type:
int anUnsignedByte = (int) aSignedByte & 0xff;
I think the other answers have covered memory representation and how you handle these depends on the context of how you plan on using it. I'll add that Java 8 added some support for dealing with unsigned types. In this case, you could use Byte.toUnsignedInt
int unsignedInt = Byte.toUnsignedInt(myByte);
A side note, if you want to print it out, you can just say
byte b = 255;
System.out.println((b < 0 ? 256 + b : b));
You can also:
public static int unsignedToBytes(byte a)
{
return (int) ( ( a << 24) >>> 24);
}
Explanation:
let's say a = (byte) 133;
In memory it's stored as: "1000 0101" (0x85 in hex)
So its representation translates unsigned=133, signed=-123 (as 2's complement)
a << 24
When left shift is performed 24 bits to the left, the result is now a 4 byte integer which is represented as:
"10000101 00000000 00000000 00000000" (or "0x85000000" in hex)
then we have
( a << 24) >>> 24
and it shifts again on the right 24 bits but fills with leading zeros. So it results to:
"00000000 00000000 00000000 10000101" (or "0x00000085" in hex)
and that is the unsigned representation which equals to 133.
If you tried to cast a = (int) a;
then what would happen is it keeps the 2's complement representation of byte and stores it as int also as 2's complement:
(int) "10000101" ---> "11111111 11111111 11111111 10000101"
And that translates as: -123
Although it may seem annoying (coming from C) that Java did not include unsigned byte in the language it really is no big deal since a simple "b & 0xFF" operation yields the unsigned value for (signed) byte b in the (rare) situations that it is actually needed. The bits don't actually change -- just the interpretation (which is important only when doing for example some math operations on the values).
If think you are looking for something like this.
public static char toUnsigned(byte b) {
return (char) (b >= 0 ? b : 256 + b);
}
Adamski provided the best answer, but it is not quite complete, so read his reply, as it explains the details I'm not.
If you have a system function that requires an unsigned byte to be passed to it, you can pass a signed byte as it will automatically treat it as an unsigned byte.
So if a system function requires four bytes, for example, 192 168 0 1 as unsigned bytes you can pass -64 -88 0 1, and the function will still work, because the act of passing them to the function will un-sign them.
However you are unlikely to have this problem as system functions are hidden behind classes for cross-platform compatibility, though some of the java.io read methods return unsighed bytes as an int.
If you want to see this working, try writing signed bytes to a file and read them back as unsigned bytes.
I am trying to use this data as a parameter to a function of Java that accepts only a byte as parameter
This is not substantially different from a function accepting an integer to which you want to pass a value larger than 2^32-1.
That sounds like it depends on how the function is defined and documented; I can see three possibilities:
It may explicitly document that the function treats the byte as an unsigned value, in which case the function probably should do what you expect but would seem to be implemented wrong. For the integer case, the function would probably declare the parameter as an unsigned integer, but that is not possible for the byte case.
It may document that the value for this argument must be greater than (or perhaps equal to) zero, in which case you are misusing the function (passing an out-of-range parameter), expecting it to do more than it was designed to do. With some level of debugging support you might expect the function to throw an exception or fail an assertion.
The documentation may say nothing, in which case a negative parameter is, well, a negative parameter and whether that has any meaning depends on what the function does. If this is meaningless then perhaps the function should really be defined/documented as (2). If this is meaningful in an nonobvious manner (e.g. non-negative values are used to index into an array, and negative values are used to index back from the end of the array so -1 means the last element) the documentation should say what it means and I would expect that it isn't what you want it to do anyway.
I happened to accidentally land on this page after wondering about the apparent asymmetry of the netty ByteBuf writeInt and readUnsignedInt methods.
After reading the interesting and educational answers I am still wondering what function you were calling when you said:
I am trying to use this data as a parameter to a function of Java that
accepts only a byte as parameter.
For what it's worth after so many years, here is my fifty cents:
Let's assume the method you are calling is updating some balance with micro amounts and that it behaves according to some well-defined set of requirements. Ie, it is considered to have a correct implementation for its intended behavior:
long processMicroPayment(byte amount) {
this.balance += amount;
return balance;
}
Basically, if you supply a positive amount it will be added to the balance, and a negative amount will effectively be subtracted from the balance. Now because it accepts a byte as its parameter the implicit assumption is that it functionally only accepts amounts between -128 and +127. So if you want to use this method to add, say, 130 to the balance, it simply will not produce the result YOU desire, because there is no way within the implementation of this method to represent an amount higher than 127. So passing it 130 will not result in your desired
behavior. Note that the method has no way of implementing a (say) AmountOutOfBoundsException because 130 will be 'interpreted' as a negative value that is still obeying the method's contract.
So I have the following questions:
are you using the method according to its (implicit or explicit) contract?
is the method implemented correctly?
am I still misunderstanding your question?
There is no unsigned byte in Java, but if you want to display a byte, you can do,
int myInt = 144;
byte myByte = (byte) myInt;
char myChar = (char) (myByte & 0xFF);
System.out.println("myChar :" + Integer.toHexString(myChar));
Output:
myChar : 90
For more information, please check, How to display a hex/byte value in Java.
Yes and no. Ive been digging around with this problem.
Like i understand this:
The fact is that java has signed interger -128 to 127..
It is possible to present a unsigned in java with:
public static int toUnsignedInt(byte x) {
return ((int) x) & 0xff;
}
If you for example add -12 signed number to be unsigned you get 244. But you can use that number again in signed, it has to be shifted back to signed and it´ll be again -12.
If you try to add 244 to java byte you'll get outOfIndexException.
Cheers..
If you have a function which must be passed a signed byte, what do you expect it to do if you pass an unsigned byte?
Why can't you use any other data type?
Unsually you can use a byte as an unsigned byte with simple or no translations. It all depends on how it is used. You would need to clarify what you indend to do with it.
As per limitations in Java, unsigned byte is almost impossible in the current data-type format. You can go for some other libraries of another language for what you are implementing and then you can call them using JNI.
If you want unsigned bytes in Java, just subtract 256 from the number you're interested in. It will produce two's complement with a negative value, which is the desired number in unsigned bytes.
Example:
int speed = 255; //Integer with the desired byte value
byte speed_unsigned = (byte)(speed-256);
//This will be represented in two's complement so its binary value will be 1111 1111
//which is the unsigned byte we desire.
You need to use such dirty hacks when using leJOS to program the NXT brick.

Convert a C# auth to java [duplicate]

I am trying to convert a signed byte in unsigned. The problem is the data I am receiving is unsigned and Java does not support unsigned byte, so when it reads the data it treats it as signed.
I tried it to convert it by the following solution I got from Stack Overflow.
public static int unsignedToBytes(byte a)
{
int b = a & 0xFF;
return b;
}
But when again it's converted in byte, I get the same signed data. I am trying to use this data as a parameter to a function of Java that accepts only a byte as parameter, so I can't use any other data type. How can I fix this problem?
The fact that primitives are signed in Java is irrelevant to how they're represented in memory / transit - a byte is merely 8 bits and whether you interpret that as a signed range or not is up to you. There is no magic flag to say "this is signed" or "this is unsigned".
As primitives are signed the Java compiler will prevent you from assigning a value higher than +127 to a byte (or lower than -128). However, there's nothing to stop you downcasting an int (or short) in order to achieve this:
int i = 200; // 0000 0000 0000 0000 0000 0000 1100 1000 (200)
byte b = (byte) 200; // 1100 1000 (-56 by Java specification, 200 by convention)
/*
* Will print a negative int -56 because upcasting byte to int does
* so called "sign extension" which yields those bits:
* 1111 1111 1111 1111 1111 1111 1100 1000 (-56)
*
* But you could still choose to interpret this as +200.
*/
System.out.println(b); // "-56"
/*
* Will print a positive int 200 because bitwise AND with 0xFF will
* zero all the 24 most significant bits that:
* a) were added during upcasting to int which took place silently
* just before evaluating the bitwise AND operator.
* So the `b & 0xFF` is equivalent with `((int) b) & 0xFF`.
* b) were set to 1s because of "sign extension" during the upcasting
*
* 1111 1111 1111 1111 1111 1111 1100 1000 (the int)
* &
* 0000 0000 0000 0000 0000 0000 1111 1111 (the 0xFF)
* =======================================
* 0000 0000 0000 0000 0000 0000 1100 1000 (200)
*/
System.out.println(b & 0xFF); // "200"
/*
* You would typically do this *within* the method that expected an
* unsigned byte and the advantage is you apply `0xFF` only once
* and than you use the `unsignedByte` variable in all your bitwise
* operations.
*
* You could use any integer type longer than `byte` for the `unsignedByte` variable,
* i.e. `short`, `int`, `long` and even `char`, but during bitwise operations
* it would get casted to `int` anyway.
*/
void printUnsignedByte(byte b) {
int unsignedByte = b & 0xFF;
System.out.println(unsignedByte); // "200"
}
I'm not sure I understand your question.
I just tried this and for byte -12 (signed value) it returned integer 244 (equivalent to unsigned byte value but typed as an int):
public static int unsignedToBytes(byte b) {
return b & 0xFF;
}
public static void main(String[] args) {
System.out.println(unsignedToBytes((byte) -12));
}
Is it what you want to do?
Java does not allow to express 244 as a byte value, as would C. To express positive integers above Byte.MAX_VALUE (127) you have to use a different integral type, like short, int or long.
Complete guide for working with unsigned bytes in Java:
Unsigned byte in Java
(Source for this answer.)
The Java Language does not provide anything like the unsigned keyword. A byte according to the language spec represents a value between −128 - 127. For instance, if a byte is cast to an int Java will interpret the first bit as the sign and use sign extension.
That being said, nothing prevents you from viewing a byte simply as 8 bits and interpret those bits as a value between 0 and 255. Just keep in mind that there's nothing you can do to force your interpretation upon someone else's method. If a method accepts a byte, then that method accepts a value between −128 and 127 unless explicitly stated otherwise.
Here are a couple of useful conversions / manipulations for your convenience:
Conversions to / from int
// From int to unsigned byte
int i = 200; // some value between 0 and 255
byte b = (byte) i; // 8 bits representing that value
// From unsigned byte to int
byte b = 123; // 8 bits representing a value between 0 and 255
int i = b & 0xFF; // an int representing the same value
(Or, if you're on Java 8+, use Byte.toUnsignedInt.)
Parsing / formatting
Best way is to use the above conversions:
// Parse an unsigned byte
byte b = (byte) Integer.parseInt("200");
// Print an unsigned byte
System.out.println("Value of my unsigned byte: " + (b & 0xFF));
Arithmetics
The 2-complement representation "just works" for addition, subtraction and multiplication:
// two unsigned bytes
byte b1 = (byte) 200;
byte b2 = (byte) 15;
byte sum = (byte) (b1 + b2); // 215
byte diff = (byte) (b1 - b2); // 185
byte prod = (byte) (b2 * b2); // 225
Division requires manual conversion of operands:
byte ratio = (byte) ((b1 & 0xFF) / (b2 & 0xFF));
There are no primitive unsigned bytes in Java. The usual thing is to cast it to bigger type:
int anUnsignedByte = (int) aSignedByte & 0xff;
I think the other answers have covered memory representation and how you handle these depends on the context of how you plan on using it. I'll add that Java 8 added some support for dealing with unsigned types. In this case, you could use Byte.toUnsignedInt
int unsignedInt = Byte.toUnsignedInt(myByte);
A side note, if you want to print it out, you can just say
byte b = 255;
System.out.println((b < 0 ? 256 + b : b));
You can also:
public static int unsignedToBytes(byte a)
{
return (int) ( ( a << 24) >>> 24);
}
Explanation:
let's say a = (byte) 133;
In memory it's stored as: "1000 0101" (0x85 in hex)
So its representation translates unsigned=133, signed=-123 (as 2's complement)
a << 24
When left shift is performed 24 bits to the left, the result is now a 4 byte integer which is represented as:
"10000101 00000000 00000000 00000000" (or "0x85000000" in hex)
then we have
( a << 24) >>> 24
and it shifts again on the right 24 bits but fills with leading zeros. So it results to:
"00000000 00000000 00000000 10000101" (or "0x00000085" in hex)
and that is the unsigned representation which equals to 133.
If you tried to cast a = (int) a;
then what would happen is it keeps the 2's complement representation of byte and stores it as int also as 2's complement:
(int) "10000101" ---> "11111111 11111111 11111111 10000101"
And that translates as: -123
Although it may seem annoying (coming from C) that Java did not include unsigned byte in the language it really is no big deal since a simple "b & 0xFF" operation yields the unsigned value for (signed) byte b in the (rare) situations that it is actually needed. The bits don't actually change -- just the interpretation (which is important only when doing for example some math operations on the values).
If think you are looking for something like this.
public static char toUnsigned(byte b) {
return (char) (b >= 0 ? b : 256 + b);
}
Adamski provided the best answer, but it is not quite complete, so read his reply, as it explains the details I'm not.
If you have a system function that requires an unsigned byte to be passed to it, you can pass a signed byte as it will automatically treat it as an unsigned byte.
So if a system function requires four bytes, for example, 192 168 0 1 as unsigned bytes you can pass -64 -88 0 1, and the function will still work, because the act of passing them to the function will un-sign them.
However you are unlikely to have this problem as system functions are hidden behind classes for cross-platform compatibility, though some of the java.io read methods return unsighed bytes as an int.
If you want to see this working, try writing signed bytes to a file and read them back as unsigned bytes.
I am trying to use this data as a parameter to a function of Java that accepts only a byte as parameter
This is not substantially different from a function accepting an integer to which you want to pass a value larger than 2^32-1.
That sounds like it depends on how the function is defined and documented; I can see three possibilities:
It may explicitly document that the function treats the byte as an unsigned value, in which case the function probably should do what you expect but would seem to be implemented wrong. For the integer case, the function would probably declare the parameter as an unsigned integer, but that is not possible for the byte case.
It may document that the value for this argument must be greater than (or perhaps equal to) zero, in which case you are misusing the function (passing an out-of-range parameter), expecting it to do more than it was designed to do. With some level of debugging support you might expect the function to throw an exception or fail an assertion.
The documentation may say nothing, in which case a negative parameter is, well, a negative parameter and whether that has any meaning depends on what the function does. If this is meaningless then perhaps the function should really be defined/documented as (2). If this is meaningful in an nonobvious manner (e.g. non-negative values are used to index into an array, and negative values are used to index back from the end of the array so -1 means the last element) the documentation should say what it means and I would expect that it isn't what you want it to do anyway.
I happened to accidentally land on this page after wondering about the apparent asymmetry of the netty ByteBuf writeInt and readUnsignedInt methods.
After reading the interesting and educational answers I am still wondering what function you were calling when you said:
I am trying to use this data as a parameter to a function of Java that
accepts only a byte as parameter.
For what it's worth after so many years, here is my fifty cents:
Let's assume the method you are calling is updating some balance with micro amounts and that it behaves according to some well-defined set of requirements. Ie, it is considered to have a correct implementation for its intended behavior:
long processMicroPayment(byte amount) {
this.balance += amount;
return balance;
}
Basically, if you supply a positive amount it will be added to the balance, and a negative amount will effectively be subtracted from the balance. Now because it accepts a byte as its parameter the implicit assumption is that it functionally only accepts amounts between -128 and +127. So if you want to use this method to add, say, 130 to the balance, it simply will not produce the result YOU desire, because there is no way within the implementation of this method to represent an amount higher than 127. So passing it 130 will not result in your desired
behavior. Note that the method has no way of implementing a (say) AmountOutOfBoundsException because 130 will be 'interpreted' as a negative value that is still obeying the method's contract.
So I have the following questions:
are you using the method according to its (implicit or explicit) contract?
is the method implemented correctly?
am I still misunderstanding your question?
There is no unsigned byte in Java, but if you want to display a byte, you can do,
int myInt = 144;
byte myByte = (byte) myInt;
char myChar = (char) (myByte & 0xFF);
System.out.println("myChar :" + Integer.toHexString(myChar));
Output:
myChar : 90
For more information, please check, How to display a hex/byte value in Java.
Yes and no. Ive been digging around with this problem.
Like i understand this:
The fact is that java has signed interger -128 to 127..
It is possible to present a unsigned in java with:
public static int toUnsignedInt(byte x) {
return ((int) x) & 0xff;
}
If you for example add -12 signed number to be unsigned you get 244. But you can use that number again in signed, it has to be shifted back to signed and it´ll be again -12.
If you try to add 244 to java byte you'll get outOfIndexException.
Cheers..
If you have a function which must be passed a signed byte, what do you expect it to do if you pass an unsigned byte?
Why can't you use any other data type?
Unsually you can use a byte as an unsigned byte with simple or no translations. It all depends on how it is used. You would need to clarify what you indend to do with it.
As per limitations in Java, unsigned byte is almost impossible in the current data-type format. You can go for some other libraries of another language for what you are implementing and then you can call them using JNI.
If you want unsigned bytes in Java, just subtract 256 from the number you're interested in. It will produce two's complement with a negative value, which is the desired number in unsigned bytes.
Example:
int speed = 255; //Integer with the desired byte value
byte speed_unsigned = (byte)(speed-256);
//This will be represented in two's complement so its binary value will be 1111 1111
//which is the unsigned byte we desire.
You need to use such dirty hacks when using leJOS to program the NXT brick.

Applying casting to primitive types

int a=128;
byte b;
b=(byte)a;
System.out.println(b);
This prints -128.
But in the Java book the same code outputs 0.
What's the difference between them?
128 represented as a 32-bit integer (int) is 00000000 00000000 00000000 10000000 in binary.
As a byte is only 8 bits, when it is cast to a byte it becomes 10000000. Because all integers in Java are signed integers using two's complement, the first bit (1) is the sign bit, therefore the value becomes -128.
Not sure why the book said the output should be 0. Are you sure the example is exactly the same in the book?
More information on the Java primitives types here and Wikipedia has a fairly comprehensive article on two's complement.
Look, 128 = 0x80, so if you cut off all but less significant byte you will get 1000 0000 (binary). This is -128 for byte.
So there is an error in you java book:)
In Java this should really print -128. If a = 256 it should print 0.
Byte is from -128 to 127, so if you cast 127 it is 127 and 128 is -128 because 127 + 1 = -128.
Right answer was posted already but id like to expand it a little.
To understand better how it works, try to read about it form other sources. #DanielGibbs provided few you could use
i suggest you also try to run code like:
for (int a = -256; a < 256; a++) {
byte b = (byte) a;
System.out.println(a + " -> " + b);
}
output of this code should let you see clearly meaning of less significant (and one most significant which determines sign) bites in int and how they are fit in byte type.
PS. -256 is not 10000000 00000000 00000001 00000000, but 11111111 11111111 11111111 00000000.

How to manually calculate the value of a typecasted byte value that exceeds the primary data type? [duplicate]

This question already has answers here:
java byte data type
(3 answers)
Closed 8 years ago.
since english isn't my main language and i've didn't find any pointers as to how to manually calculate the new number.
Example:
byte b = (byte) 720;
System.out.println(b); // -48
I know that most primary data types use the two complement.
Byte value ranges from -128 to 127, so it's expected to round the number down to something that fits in byte.
The Question is how do i manually calculate the -48 of the typecasted 720? I've read that i have to convert it to two complement, so taking the binary number, searching from right to left for the first one and then inverting all others and since byte only has 8 bits, take the first 8 bits. But that didn't quite work for me, it would be helpful if you would tell me how to calculate a typecasted number that doesn't fit into byte. Thanks for reading! :)
The binary representation of 702 is
10 1101 0000
Get rid of everything except the last 8 bits (because that's what fits into a byte).
1101 0000
Because of the leading 1, get the complement
0010 1111
and add 1
0011 0000
and negate the value. Gives -48.
In Java, integral types are always 2's complement. Section 4.2 of the JLS states:
The integral types are byte, short, int, and long, whose values are 8-bit, 16-bit, 32-bit and 64-bit signed two's-complement integers
You can mask out the least significant 8 bits.
int value = 720;
value &= 0xFF;
But that leaves a number in the range 0-255. Numbers higher than 127 represent negative numbers for bytes.
if (value > Byte.MAX_VALUE)
value -= 1 << 8;
This manually yields the -48 that the (byte) cast yields.
First what happens is the value (in binary) is truncated.
720 binary is 0b1011010000
We can only fit 8 bits 0b11010000
first digit 1, so the value is negative.
2's compliment gives you -48.
This is close to redundant with the answer posted by rgettman, but since you inquired about the two's complement, here is "manually" taking the 2's complement, rather than simply subtracting 256 as in that answer.
To mask the integer down to the bits that will be considered for a byte, combine it bitwise with 11111111.
int i = 720;
int x = i & 0xFF;
Then to take the two's complement:
if (x >> 7 == 1) {
x = -1 * ((x ^ 0xFF) + 1);
}
System.out.println(x);

Bitwise AND, Bitwise Inclusive OR question, in Java

I've a few lines of code within a project, that I can't see the value of...
buffer[i] = (currentByte & 0x7F) | (currentByte & 0x80);
It reads the filebuffer from a file, stored as bytes, and then transfers then to buffer[i] as shown, but I can't understand what the overall purpose is, any ideas?
Thanks
As the other answers already stated, (currentByte & 0x7F) | (currentByte & 0x80) is equivalent to (currentByte & 0xFF). The JLS3 15.22.1 says this is promoted to an int:
When both operands of an operator &,
^, or | are of a type that is
convertible (§5.1.8) to a primitive
integral type, binary numeric
promotion is first performed on the
operands (§5.6.2). The type of the
bitwise operator expression is the
promoted type of the operands.
because JLS3 5.6.2 says that when currentByte has type byte and 0x7F is an int (and this is the case), then both operands are promoted to int.
Therefore, buffer will be an array of element type int or wider.
Now, by performing & 0xFF on an int, we effectively map the original byte range -128..127 into the unsigned range 0..255, an operation often used by java.io streams for example.
You can see this in action in the following code snippet. Note that to understand what is happening here, you have to know that Java stores integral types, except char, as 2's complement values.
byte b = -123;
int r = b;
System.out.println(r + "= " + Integer.toBinaryString(r));
int r2 = b & 0xFF;
System.out.println(r2 + "= " + Integer.toBinaryString(r2));
Finally, for a real-world example, check out the Javadoc and implementation of the read method of java.io.ByteArrayInputStream:
/**
* Reads the next byte of data from this input stream. The value
* byte is returned as an <code>int</code> in the range
* <code>0</code> to <code>255</code>. If no byte is available
* because the end of the stream has been reached, the value
* <code>-1</code> is returned.
*/
public synchronized int read() {
return (pos < count) ? (buf[pos++] & 0xff) : -1;
}
(currentByte & 0x7F) | (currentByte & 0x80)
is equivalent to
currentByte & (0x7F | 0x80)
which equals
currentByte & 0xFF
which is exactly the same as
currentByte
Edit: I only looked at the right side of the assignment, and I still think the equivalance is true.
However, it seems like the code wants to cast the signed byte to a larger type while interpreting the byte as unsigned.
Is there an easier way to cast signed-byte to unsigned in java?
I think someone did too much thinking here. That's just not right.
I have but one remark
The original author was worried about the run-time replacing the byte with a native signed integer (presumably 32-bit) and is explicitly trying to tell us something about the sign bit being "special"?
It's code left behind. Unless you know you're on a fishy run-time? What's the type of the 'buffer' anyway?
The complicated bitwise logic is completely superfluous.
for (int i = 0; i < buffer.length; i++) {
buffer[i] = filebuffer[currentPosition + i] & 0xff;
}
does the same thing. If buffer is declared as an array of bytes you may even leave out the & 0xff, but unfortunately the declaration is not shown.
The reason may be that the original developer was confused by bytes being signed in Java.
The result of a bitwise AND operation has a 1 on that bits where both bits are 1 while the result of a bitwise OR operation hase a on that bits where either one of bot bits is 1.
So an example evaluation for the value 0x65:
01100101 0x65
& 01111111 0x7F
===============
01100101 0x65
01100101 0x65
& 10000000 0x80
===============
00000000 0x00
01100101 0x65
| 00000000 0x00
===============
01100101 0x65
The good thing about these kinds of logical operations: you can try every possible combination (all 256 of them) and verify that you get the answer you expected.
Turns out, the file which the byte was being read from was in a signed bit notation, and of a different length, therefore it was requried to perform this task to allow it to be extended to the java int type, while retaining its correct sign :)

Categories

Resources