I have to convert my bytes to unsigned char and unsigned short , it is done like this in iOS
latitude = (unsigned char)(bytebuffr.getchar(0)) + ((unsigned short)(bytebuffr.getchar(1)& 0xF)) << 8);
How can I achieve this in my android code. please help
already tried this in android but not working,
lattitude = (short) ((getUnsignedByte((byte) (bb.getChar(0) & 0xFF))) +
getUnsignedByte((byte) ((bb.getChar(1) & 0x0F))) << 8);
bb is bytebuffer and bb.getchar is giving me the bytes which is being read from bytebuffer
You don't need to convert from char to short in this case. Since bb is a ByteBuffer, use getShort if you want to read two bytes from the buffer and use them as a signed 16-bit number. Use getChar if you need to read two bytes from the buffer (not one!) and use them as an unsigned 16-bit number. I suspect you're thinking that getChar only reads a single byte. It doesn't. char is 16 bits wide. Also, char is an unsigned integral type in Java. Although it's used to represent characters (loosely) in strings, it's an integral (whole number) type. The integral types are:
byte: 8-bit signed: -128 to 127, inclusive
short: 16-bit signed; -32768 to 32767, inclusive
char: 16-bit unsigned: 0 to 65535, inclusive (aka '\u0000' to '\uffff')
int: 32-bit signed: -2147483648 to 2147483647, inclusive
long: 32-bit signed: -9223372036854775808 to 9223372036854775807, inclusive
If you did need to convert: char is an unsigned 16-bit type. short is a signed 16-bit type. To use the same bits in a short as you have in a char, you do this:
short s = (short)ch;
No need for masking off the first byte or anything like that.
Related
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.
I was reading through examples trying to understand how to convert signed bytes to unsigned integer counter parts.
The most popular method that I have come across is:
a & 0xFF
Where a is the signed byte.
My question is why is 0xFF stored as unsigned? Are all hex values stored as unsigned? If so why?
And how does "and"-ing turn off the sign bit in the sign integer?
It would be great if someone could break down the process step by step.
You probably saw this in code that converted a byte to an integer, where they wanted to treat the byte as an unsigned value in the range 0-255. It does not apply to integers in general. If you want to make an integer a "unsigned", you can do:
int unsignedA = a & 0x7FFFFFFF;
This will ensure that unsignedA is positive - but it does that by chopping off the high bit, so for example if a was -1, then unsignedA is Integer.MAX_VALUE.
There is no way to turn a 32-bit signed Java integer into a 32-bit unsigned Java integer because there is no datatype in Java for a 32-bit unsigned integer. The only unsigned integral datatype in Java is 16 bits long: char.
If you want to store a 32-bit unsigned integral value in Java, you need to store it in a long:
long unsignedA = a & 0xFFFFFFFFL;
To elaborate on Erwin's answer about converting a byte to an integer: In Java, byte is a signed integer type. That means it has values in the range -128 to 127. If you say:
byte a;
int b;
a = -64;
b = a;
The language will preserve the value; that is, it will set b to -64.
But if you really want to convert your byte to a value from 0 to 255 (which I guess you call the "unsigned counterpart" of the byte value), you can use a & 0xFF. Here's what happens:
Java does not do arithmetic directly on byte or short types. So when it sees a & 0xFF, it converts both sides to an int. The hex value of a, which is a byte, looks like
a = C0
When it's converted to a 32-bit integer, the value (-64) has to be preserved, so that means the 32-bit integer has to have 1 bits in the upper 24 bits. Thus:
a = C0
(int)a = FFFFFFC0
But then you "and" it with 0xFF:
a = C0
(int)a = FFFFFFC0
& 000000FF
--------
a & FF = 000000C0
And the result is an integer in the range 0 to 255.
In Java, literals (1, 0x2A, etc) are positive unless you explicitly indicate that they are negative. It's how we intuitively write numbers.
This previous question answers you question about converting to unsigned. Understanding Java unsigned numbers
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.
I have a uint8 (unsigned 8 bit integer) coming in from a UDP packet. Java only uses signed primitives. How do I parse this data structure correctly with java?
Simply read it as as a byte and then convert to an int.
byte in = udppacket.getByte(0); // whatever goes here
int uint8 = in & 0xFF;
The bitmask is needed, because otherwise, values with bit 8 set to 1 will be converted to a negative int. Example:
This: 10000000
Will result in: 11111111111111111111111110000000
So when you afterwards apply the bitmask 0xFF to it, the leading 1's are getting cancelled out. For your information: 0xFF == 0b11111111
0xFF & number will treat the number as unsigned byte. But the resultant type is int
You can store 8-bit in a byte If you really need to converted it to an unsigned value (and often you don't) you can use a mask
byte b = ...
int u = b & 0xFF; // unsigned 0 .. 255 value
You can do something like this:
int value = eightBits & 0xff;
The & operator (like all integer operators in Java) up-casts eightBits to an int (by sign-extending the sign bit). Since this would turn values greater than 0x7f into negative int values, you need to then mask off all but the lowest 8 bits.
You could simply parse it into a short or an int, which have enough range to hold all the values of an unsigned byte.
Is there a way to declare an unsigned int in Java?
Or the question may be framed as this as well:
What is the Java equivalent of unsigned?
Just to tell you the context I was looking at Java's implementation of String.hashcode(). I wanted to test the possibility of collision if the integer were 32 unsigned int.
Java does not have a datatype for unsigned integers.
You can define a long instead of an int if you need to store large values.
You can also use a signed integer as if it were unsigned. The benefit of two's complement representation is that most operations (such as addition, subtraction, multiplication, and left shift) are identical on a binary level for signed and unsigned integers. A few operations (division, right shift, comparison, and casting), however, are different. As of Java SE 8, new methods in the Integer class allow you to fully use the int data type to perform unsigned arithmetic:
In Java SE 8 and later, you can use the int data type to represent an unsigned 32-bit integer, which has a minimum value of 0 and a maximum value of 2^32-1. Use the Integer class to use int data type as an unsigned integer. Static methods like compareUnsigned, divideUnsigned etc have been added to the Integer class to support the arithmetic operations for unsigned integers.
Note that int variables are still signed when declared but unsigned arithmetic is now possible by using those methods in the Integer class.
Whether a value in an int is signed or unsigned depends on how the bits are interpreted - Java interprets bits as a signed value (it doesn't have unsigned primitives).
If you have an int that you want to interpret as an unsigned value (e.g. you read an int from a DataInputStream that you know should be interpreted as an unsigned value) then you can do the following trick.
int fourBytesIJustRead = someObject.getInt();
long unsignedValue = fourBytesIJustRead & 0xffffffffL;
Note, that it is important that the hex literal is a long literal, not an int literal - hence the 'L' at the end.
We needed unsigned numbers to model MySQL's unsigned TINYINT, SMALLINT, INT, BIGINT in jOOQ, which is why we have created jOOU, a minimalistic library offering wrapper types for unsigned integer numbers in Java. Example:
import static org.joou.Unsigned.*;
// and then...
UByte b = ubyte(1);
UShort s = ushort(1);
UInteger i = uint(1);
ULong l = ulong(1);
All of these types extend java.lang.Number and can be converted into higher-order primitive types and BigInteger. Hope this helps.
(Disclaimer: I work for the company behind these libraries)
For unsigned numbers you can use these classes from Guava library:
UnsignedInteger
UnsignedLong
They support various operations:
plus
minus
times
mod
dividedBy
The thing that seems missing at the moment are byte shift operators. If you need those you can use BigInteger from Java.
Perhaps this is what you meant?
long getUnsigned(int signed) {
return signed >= 0 ? signed : 2 * (long) Integer.MAX_VALUE + 2 + signed;
}
getUnsigned(0) → 0
getUnsigned(1) → 1
getUnsigned(Integer.MAX_VALUE) → 2147483647
getUnsigned(Integer.MIN_VALUE) → 2147483648
getUnsigned(Integer.MIN_VALUE + 1) → 2147483649
Use char for 16 bit unsigned integers.
There are good answers here, but I don’t see any demonstrations of bitwise operations. Like Visser (the currently accepted answer) says, Java signs integers by default (Java 8 has unsigned integers, but I have never used them). Without further ado, let‘s do it...
RFC 868 Example
What happens if you need to write an unsigned integer to IO? Practical example is when you want to output the time according to RFC 868. This requires a 32-bit, big-endian, unsigned integer that encodes the number of seconds since 12:00 A.M. January 1, 1900. How would you encode this?
Make your own unsigned 32-bit integer like this:
Declare a byte array of 4 bytes (32 bits)
Byte my32BitUnsignedInteger[] = new Byte[4] // represents the time (s)
This initializes the array, see Are byte arrays initialised to zero in Java?. Now you have to fill each byte in the array with information in the big-endian order (or little-endian if you want to wreck havoc). Assuming you have a long containing the time (long integers are 64 bits long in Java) called secondsSince1900 (Which only utilizes the first 32 bits worth, and you‘ve handled the fact that Date references 12:00 A.M. January 1, 1970), then you can use the logical AND to extract bits from it and shift those bits into positions (digits) that will not be ignored when coersed into a Byte, and in big-endian order.
my32BitUnsignedInteger[0] = (byte) ((secondsSince1900 & 0x00000000FF000000L) >> 24); // first byte of array contains highest significant bits, then shift these extracted FF bits to first two positions in preparation for coersion to Byte (which only adopts the first 8 bits)
my32BitUnsignedInteger[1] = (byte) ((secondsSince1900 & 0x0000000000FF0000L) >> 16);
my32BitUnsignedInteger[2] = (byte) ((secondsSince1900 & 0x000000000000FF00L) >> 8);
my32BitUnsignedInteger[3] = (byte) ((secondsSince1900 & 0x00000000000000FFL); // no shift needed
Our my32BitUnsignedInteger is now equivalent to an unsigned 32-bit, big-endian integer that adheres to the RCF 868 standard. Yes, the long datatype is signed, but we ignored that fact, because we assumed that the secondsSince1900 only used the lower 32 bits). Because of coersing the long into a byte, all bits higher than 2^7 (first two digits in hex) will be ignored.
Source referenced: Java Network Programming, 4th Edition.
It seems that you can handle the signing problem by doing a "logical AND" on the values before you use them:
Example (Value of byte[] header[0] is 0x86 ):
System.out.println("Integer "+(int)header[0]+" = "+((int)header[0]&0xff));
Result:
Integer -122 = 134
Just made this piece of code, wich converts "this.altura" from negative to positive number. Hope this helps someone in need
if(this.altura < 0){
String aux = Integer.toString(this.altura);
char aux2[] = aux.toCharArray();
aux = "";
for(int con = 1; con < aux2.length; con++){
aux += aux2[con];
}
this.altura = Integer.parseInt(aux);
System.out.println("New Value: " + this.altura);
}
You can use the Math.abs(number) function. It returns a positive number.