Understanding Java bytes - java

So at work yesterday, I had to write an application to count the pages in an AFP file. So I dusted off my MO:DCA spec PDF and found the structured field BPG (Begin Page) and its 3-byte identifier. The app needs to run on an AIX box, so I decided to write it in Java.
For maximum efficiency, I decided that I would read the first 6 bytes of each structured field and then skip the remaining bytes in the field. This would get me:
0: Start of field byte
1-2: 2-byte length of field
3-5: 3-byte sequence identifying the type of field
So I check the field type and increment a page counter if it's BPG, and I don't if it's not. Then I skip the remaining bytes in the field rather than read through them. And here, in the skipping (and really in the field length) is where I discovered that Java uses signed bytes.
I did some googling and found quite a bit of useful information. Most useful, of course, was the instruction to do a bitwise & to 0xff to get the unsigned int value. This was necessary for me to get a length that could be used in the calculation for the number of bytes to skip.
I now know that at 128, we start counting backwards from -128. What I want to know is how the bitwise operation works here--more specifically, how I arrive at the binary representation for a negative number.
If I understand the bitwise & properly, your result is equal to a number where only the common bits of your two numbers are set. So assuming byte b = -128, we would have:
b & 0xff // 128
1000 0000-128
1111 1111 255
---------
1000 0000 128
So how would I arrive at 1000 0000 for -128? How would I get the binary representation of something less obvious like -72 or -64?

In order to obtain the binary representation of a negative number you calculate two's complement:
Get the binary representation of the positive number
Invert all the bits
Add one
Let's do -72 as an example:
0100 1000 72
1011 0111 All bits inverted
1011 1000 Add one
So the binary (8-bit) representation of -72 is 10111000.
What is actually happening to you is the following: You file has a byte with value 10111000. When interpreted as an unsigned byte (which is probably what you want), this is 88.
In Java, when this byte is used as an int (for example because read() returns an int, or because of implicit promotion), it will be interpreted as a signed byte, and sign-extended to 11111111 11111111 11111111 10111000. This is an integer with value -72.
By ANDing with 0xff you retain only the lowest 8 bits, so your integer is now 00000000 00000000 00000000 10111000, which is 88.

What I want to know is how the bitwise operation works here--more specifically, how I arrive at the binary representation for a negative number.
The binary representation of a negative number is that of the corresponding positive number bit-flipped with 1 added to it. This representation is called two's complement.

I guess the magic here is that the byte is stored in a bigger container, likely a 32 bit int. And if the byte was interpreted as being a signed byte it gets expanded to represent the same number in the 32 bit int, that is if the most significant bit (the first one) of the byte is a 1 then in the 32 bit int all the bits left of that 1 are also turned to 1 (that's due to the way negative numbers are represented, two's complement).
Now, if you & 0xFF that int you cut off those 1's and end up with a "positive" int representing the byte value you've read.

Not sure what you really want :) I assume you are asking how to extract a signed multi-byte value? First, look at what happens when you sign extend a single byte:
byte[] b = new byte[] { -128 };
int i = b[0];
System.out.println(i); // prints -128!
So, the sign is correctly extendet to 32 bits without doing anything special. The byte 1000 0000 extends correctly to 1111 1111 1111 1111 1111 1111 1000 0000.
You already know how to suppress sign extension by AND'ing with 0xFF - for multi byte values, you want only the sign of the most significant byte to be extendet, and the less significant bytes you want to treat as unsigned (example assumes network byte order, 16-bit int value):
byte[] b = new byte[] { -128, 1 }; // 0x80, 0x01
int i = (b[0] << 8) | (b[1] & 0xFF);
System.out.println(i); // prints -32767!
System.out.println(Integer.toHexString(i)); // prints ffff8001
You need to suppress the sign extension of every byte except the most significant one, so to extract a signed 32-bit int to a 64-bit long:
byte[] b = new byte[] { -54, -2, -70, -66 }; // 0xca, 0xfe, 0xba, 0xbe
long l = ( b[0] << 24) |
((b[1] & 0xFF) << 16) |
((b[2] & 0xFF) << 8) |
((b[3] & 0xFF) );
System.out.println(l); // prints -889275714
System.out.println(Long.toHexString(l)); // prints ffffffffcafebabe
Note: on intel based systems, bytes are often stored in reverse order (least significant byte first) because the x86 architecture stores larger entities in this order in memory. A lot of x86 originated software does use it in file formats, too.

To get the unsigned byte value you can either.
int u = b & 0xFF;
or
int u = b < 0 ? b + 256 : b;

For bytes with bit 7 set:
unsigned_value = signed_value + 256
Mathematically when you compute with bytes you compute modulo 256. The difference between signed and unsigned is that you choose different representatives for the equivalence classes, while the underlying representation as a bit pattern stays the same for each equivalence class. This also explains why addition, subtraction and multiplication have the same result as a bit pattern, regardless of whether you compute with signed or unsigned integers.

Related

Can Java's byte actually store 32bit?

My goal is to understand how byte is stored in Java.
System.out.println("(byte) 0xFF:\r\n" +
Integer.toBinaryString((byte) 0xFF));
My expected result of (byte) 0xFF is 0xFF.
My actual result of (byte) 0xFF is 0xFFFFFFFF
The output:
(byte) 0xFF:
11111111111111111111111111111111
If this is true, does storing negative number in byte actually is no different than storing negative number in int?
toBinaryString accepts an int. Your input was just autopromoted to int, hence it was represented with 32 digits (0xFF == -1 in two's complement, which promoted to int becomes 0xFFFFFFFF which is still -1 but represented with 32 bits, still in two's complement).
Notice that
If the unsigned magnitude is zero, it is represented by a single zero character '0' ('\u0030'); otherwise, the first character of the representation of the unsigned magnitude will not be the zero character.
Which means that if there are leading 0s they won't be part of the output (unless the output is 0), which means you'll get less than 32 digits.
When the byte is implicitly re-cast as an integer, it sees the first bit as a sign bit and when it stretches out to be 4 bytes long, it retains it's value as negative. You've effectively overflowed to the smallest negative integer value.
Java bytes are signed and can represent the values -128 to 127, and a hex value of 0xff is treated as -1. When you call Integer.toBinaryString, the byte is cast to an int, preserving the sign. The way this works is called sign extension, and the highest bit from the byte is copied all the way up. This is why you see 0xfffff...
To perform an unsigned conversion, mask the value with 0xff, which itself an int unless specified otherwise.
byte b = (byte) 0xff;
Integer.toBinaryString(b & 0xff);
And to answer your original question, Java doesn't really support a byte type as you might expect. It's always a 32-bit value except when dealing with byte arrays and byte buffers. Using a type of byte simply informs the JVM to perform certain type casting rules which have the effect of clearing or setting the upper bits accordingly.

conver file input to byte array of decimal instead of decimals from signed 2's complement [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.

Storing and sending array of Integers as bytes in 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.

Converting 0xFF gives me -1 -> Signed vs Unsigned?

Here is my code:
byte b = (byte) 0xFF;
System.out.println(b);
I expect to see 255, but instead I see -1. What's happening? Is the compiler using a signed instead of an unsigned byte?
Maybe you are confused about the difference between storage and representation.
As the others told you, Java only uses signed integral types. As a byte is only 8 bit, this means you have a range from -128 to 127. But keep in mind: This is only a decimal representation that does not tell you about the binary storage!
A better reminder for the range of Java's byte type would be the following (decimal) representation:
0 1 ... 126 127 -128 -127 ... -2 -1
This directly corresponds to the following binary representation:
00000000 00000001 ... 11111110 11111111
The signed decimal representation is called the two's complement. As you can see, the binary value 11111111, which is exactly 0xFF, corresponds to the (signed) decimal value -1.
If you now send this value via a stream, you will get the full 0xFF value, regardless what you see in a Java program's console output.
In Java type byte is signed, it is not possible to use an "unsigned byte" in java. A workaround would be to use short types
Everytime you operate on a byte variable in Java, (byte) 0xFF is going to be implicitly converted to (int) 0xFFFFFF (i.e. -1). You can do 0xFFFFFF & 0xFF and then you'll get (int) 255 as you wish (you will never be able to get (byte) 255, only (int) 255).
If you only need to store bytes, it doesn't matter how 0xFF is printed on the screen, it's still (byte) 0xFF internally. If you need to operate on them (comparing to an int, adding, subtracting, converting to a string, printing on the screen, and basically anything else), then you need to be aware that they'll get converted to int 0xFFFFFF which is interpreted -1.

Why byte b = (byte) 0xFF is equals to integer -1?

Why byte b = (byte) 0xFF is equal to integer -1?
Ex:
int value = byte b = (byte) 0xFF;
System.out.println(value);
it will print -1?
Bytes are signed in Java. In binary 0x00 is 0, 0x01 is 1 and so on but all 1s (ie 0xFF) is -1, 0xFE is -2 and so on. See Two's complement, which is the binary encoding mechanism used.
b is promoted to an int in determining which overload of system.out.println to call.
All bytes in Java are signed.
The signed byte 0xff represents the value -1. This is because Java uses two's complement to represent signed values. The signed byte 0xff represents -1 because its most significant bit is 1 (so therefore it represents a negative value) and its value is -128 + 64 + 32 + 16 + 8 + 4 + 2 + 1 = -1.
perhaps your confusion comes from why (byte)0xFF is somehow equal to (int)0xFFFFFFFF. What's happening here is the promotion from smaller to larger signed types causes the smaller value to be sign extended, whereby the most significant bit is copied to all of the new bits of the promoted value. an unsigned type will not become sign-extended, they get zero extended, the new bits will always be zero.
If it helps you to swallow it, think of it this way, every integer of any size also has some 'phantom' bits that are too significant to be represented. they are there, just not stored in the variable. a negative number has those bits nonzero, and positive numbers have all zeros for phantom bits when you promote a smaller value to a larger one, those phantom bits become real bits.
If you are using a signed int then 0xFF = -1 due to the 2-complement.
This wiki article explains it well, see the table on the right:
http://en.wikipedia.org/wiki/Two%27s_complement
Because Java (and most languages) represent negative integer values using two's-complement math. In two's-complement, 0xFF (11111111) represents (in a signed int) the value -1.
reduced modulo
byte = 256
0xff = 255
255 / 256 -> remainder 255
So 255 - 256 = -1
Simple Logic
Cheers
Its not just Java that does 2's complement math. That is the way every microprocessor and DSP that I can think of does math. So, its the way every programming language represents it.

Categories