Can anyone explain Java arithmetics to me? [duplicate] - java

This question already has answers here:
Packing bytes into a long with |= is giving unexpected results
(1 answer)
Issues when converting bytes to integers (Java specific?)
(2 answers)
Closed 24 days ago.
I am trying to convert a byte array of 4 to an integer.
The code i am using is this:
byte[] bytes = new byte[4];
bytes[0] = (byte)0x95;
bytes[1] = (byte)0x19;
bytes[2] = (byte)0x07;
bytes[3] = (byte)0x00;
int number = bytes[0] + (bytes[1] << 8) + (bytes[2] << 16) + (bytes[3] << 24);
When running this exact code on my machine, the expected result would be 0x00071995, but somehow i get the result 0x00071895. How? Why?
java 19.0.1 2022-10-18
Java(TM) SE Runtime Environment (build 19.0.1+10-21)

A java byte is signed, and 0x95 represents a negative number with value -107 (since the leading bit is set). When it's promoted to a wider integer as part of the arithmetic operation, it ends up being sign-extended to 0xffffff95 (i.e. still -107), or 256 less than your desired value, thus causing the discrepancy in the next byte up.
Unsigned and signed addition should not give any differences in binary
There is no difference as long as you stay within the same width of integer type. The quantity 0x95 equivalent to the quantity -0x6B, modulo 256. However, the two are not equivalent modulo 4294967296. 0x95 simply does not overflow the signed range of a 32-bit int.
Another way of looking at this - signed and unsigned addition themselves do not give a difference in the binary representation. However, signed and unsigned promotion do cause a difference - a signed value is sign-extended (i.e. padded with 1s at the left when the sign bit was already 1) but an unsigned value is zero extended. A signed 8-bit 0x95 sign-extends to 0xffffff95, and an unsigned 8-bit 0x95 zero-extends to 0x00000095.
If I cast every byte[] element to long and i do a logical and with 0xFF i get the expected result
This ensures that you zero-extend instead of sign-extending; the undesired leading sign bits are forced to zero by the logical AND.

Related

Why does 0b1111_1111 cause a compiler error "int cannot be converted to byte" but not 0b111_1111? [duplicate]

This question already has answers here:
Understanding Java data types
(2 answers)
How to represent 11111111 as a byte in java
(2 answers)
JAVA: why binary literal for byte with negative sign is being considered as integer type?
(5 answers)
Closed 1 year ago.
byte b = 0b1111_1111;
byte c = 0b111_1111;
byte d = 0b0111_1111;
The first line causes a compilation error: incompatible types. I also tried 0xFF and decimal, the same. Thanks.
And I think byte means cannot be larger than what 8 bits hold. 0b1111_1111 is 8 bits.
All basic integer types in Java are signed. To be exact, byte, short, int and long are signed big endian two complement integers. That means that they run from - 2n-1 to 2n-1 - 1 where n is the number of bits - 8 for a byte (Byte.SIZE in Java), and therefore the range is from -128 to 127.
The number you are using is always an integer; number literals always are. However, the integer is actually the value 0x000000FF in hexadecimals. That cannot be stored as it is higher than 127. You can however do an explicit conversion; your value does consist of 8 bits after all.
byte b = (byte) 0b1111_1111
works because it simply disregards the 24 bits from the left hand side of the value. Now if you print it you will get -1 as value though as 0b1111_1111 represents 1 in 8 bit two complement form.
If you need it to represent the integer value 255 then you need to perform the following little trick:
int i = b & 0xFF;
which will actually do the following:
First it will convert b to the value 0xFFFFFFFF as integer using sign extension as all calculations default to integer, and it still thinks that b represents -1 after all.
Then it performs a bitwise AND with the value 0x000000FF (which is called a "mask"), resulting of course in the same value 0x000000FF which represents 255.
If you think this is a nuisance then you are right. Java should have used unsigned bytes, but it decided to use only one particular integer type that is signed. Maybe a bit overzealous but still a big improvement over e.g. C where you have way too many integer formats, and each of them may be represented differently on various machines.

Java byte to short convert randomly attached 0xff problem

I am trying to cast from byte to short, but the value is randomly attached to 0xff. Is there a way to handle it normally?
short[] shortArray = new short[size];
for (int index = 0; index < size; index++)
shortArray[index] = (short) byteArray[index];
The negative numbers always must have 1 in leftmost bit.
If byte array has negative numbers, their representation in short format requires left byte to be 0xff to keep the same negative value.
For example:
the decimal byte value -2 is binary 0b1111_1110 or hexadecimal 0xfe
the decimal short value -2 is binary 0b1111_1111_1111_1110 or hexadecimal 0xfffe
Looks like you want to do an unsigned conversion (e.g. got results in range [0..255]).
byte is a signed type in Java, so converting negative byte values to short will produce negative numbers (and in two's complement system you'll see 0xff prefix).
Bit representation, however, is same for signed and unsigned bytes, for example (byte) 0xFF means 255 as unsigned, but is -1 if treated as signed one.
Unsigned conversion can be done by implicit promotion to int, picking 8 low bits using AND and downcasting result to short:
shortArray[index] = (short) (byteArray[index] & 0xFF);

Can unsigned integer vaule is there in java? if then how to declare it? [duplicate]

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.

Reading bytes in Java

I am trying to understand how the following line of code works:
for (int i = 0; i < numSamples; i++) {
short ampValue = 0;
for (int byteNo = 0; byteNo < 2; byteNo++) {
ampValue |= (short) ((data[pointer++] & 0xFF) << (byteNo * 8));
}
amplitudes[i] = ampValue;
}
As far as I understand, this is reading 2 bytes (as 2 bytes per sample) in a inclusive manner, i.e. the ampValue is composed of two byte reads. The data is the actual data sample (file) and the pointer is increasing to read it upto the last sample. But I don't understand this part:
"data[pointer++] & 0xFF) << (byteNo * 8)); "
Also, I am wondering whether it makes any difference if I want to read this as a double instead of short?
Looks like data[] is the array of bytes.
data[pointer++] gives you a byte value in the range [-128..127].
0xFF is an int contstant, so...
data[pointer++] & 0xFF promotes the byte value to an int value in the range [-128..127]. Then the & operator zeroes out all of the bits that are not set in 0xFF (i.e., it zeroes out the 24 upper bits, leaving only the low 8 bits.
The value of that expression now will be in the range [0..255].
The << operator shifts the result to the left by (byteNo * 8) bits. That's the same as saying, it multiplies the value by 2 raised to the power of (byteNo * 8). When byteNo==0, it will multiply by 2 to the power 0 (i.e., it will multiply by 1). When byteNo==1, it will multiply by 2 to the power 8 (i.e., it will multiply by 256).
This loop is creating an int in the range [0..65535] (16 bits) from each pair of bytes in the array, taking the first member of each pair as the low-order byte and the second member as the high-order byte.
It won't work to declare ampValue as double, because the |= operator will not work on a double, but you can declare the amplitudes[] array to be an array of double, and the assignment amplitudes[i] = ampValue will implicitly promote the value to a double value in the range [0.0..65535.0].
Additional info: Don't overlook #KevinKrumwiede's comment about a bug in the example.
In Java, all bytes are signed. The expression (data[pointer++] & 0xFF) converts the signed byte value to an int with the value of the byte if it were unsigned. Then the expression << (byteNo * 8) left-shifts the resulting value by zero or eight bits depending on the value of byteNo. The value of the whole expression is assigned with bitwise or to ampValue.
There appears to be a bug in this code. The value of ampValue is not reset to zero between iterations. And amplitude is not used. Are those identifiers supposed to be the same?
Let's break down the statement:
|= is the bitwise or and assignment operator. a |= b is equivalent to a = a | b.
(short) casts the int element from the data array to a short.
pointer++ is a post-increment operation. The value of pointer will be returned and used and then immediately incremented every single time it's accessed in this fashion - this is beneficial in this case because the outer-loop is cycling through 2-byte samples (via the inner loop) from the contiguous data buffer, so this keeps incrementing.
& is the bitwise AND operator and 0xFF is the hexadecimal value for the byte 0b11111111 (255 in decimal); the expression data[pointer++] & 0xFF is basically saying, for each bit in the byte retrieved from the data array, AND it with 1. In this context, it forces Java, which by default stores signed byte objects (i.e. values from -128 to 127 in decimal), to return the value as an unsigned byte (i.e. values from 0 to 255 decimal).
Since your samples are 2 bytes long, you need to shift the second lot of 8 bits left, as the most significant bits, using the left bit-shift operator <<. The byteNo * 8 ensures that you're only shifting bits when it's the second of the two bytes.
After the two bytes have been read, ampValue will now contain the value of the sample as a short.

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);

Categories

Resources