I'm trying to solve this problem: I have a byte value (1 byte) and I need to transform this value into a long value (8 bytes). But what I want is just replace the first byte of the long variable with the byte value I had before.
A example:
My Byte Value: 11001101
My Long Value: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000
What I want: 00000000 00000000 00000000 00000000 00000000 00000000 00000000 11001101
Simple as that!
I'm trying to do this (example):
byte b = -112;
long l = 0;
l = l | b;
System.out.println(l);
But I get the result -112! In my understanding, the java bit or operator should do an "or" with the first byte of the long value and the byte value. Instead, the or operator is copying the 2-complement representation of the byte value into the long value, and this is not what I want.
The result I was expecting in that case was 144, since -112 is 10010000, which is 144 when considering a unsigned value.
Hope you understand me. Thanks!
What happens here is that b is cast to long, and this is done via sign extension: the most-significant bit (1) is repeated, hence 7 11111111 bytes are used as padding. The remedy here is to explicitly consider only the 8 least-significant bits in the resulting value, using a bitwise and (&):
l = l | ((long)b & 0xff);
Java promotes the signed byte to a signed long before doing math operations, and that sign extends the byte.
To fix it, you can do this:
l = l | (0xFF & (long)b))
or
l |= 0xFF & (long)b
(This works because 0xFF is a positive int value. If it was a byte, it'd also get sign extended to a negative long.) (Casting b to an int here would work as well as casting to a long.)
Related
What I want to do is storing a 64-bit unsigned integer as a Long type, preserving its interval binary representation.
For example, I want to save
2^63-1 = 9223372036854775807 as it is (9223372036854775807) (∵ 2^63-1 <= Long.MAX_VALUE)
and
2^63 = 9223372036854775808 = 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000(2) as -9223372036854775808
because 10000000 00000000 00000000 00000000 00000000 00000000 00000000 00000000(2) is -9223372036854775808's binary representation for the signed 64-bit integer type.
Likewise, I want to save 2^64-1 = 18446744073709551615 as -1
because (unsigned) 18446744073709551615 = 0xFFFFFFFFFFFFFFFF and (signed long) -1 = 0xFFFFFFFFFFFFFFFF
JavaDoc for BigInteger.longValue() says that
Converts this BigInteger to a long. This conversion is analogous to a
narrowing primitive conversion from long to int as defined in section
5.1.3 of The Java™ Language Specification: if this BigInteger is too big to fit in a long, only the low-order 64 bits are returned. Note
that this conversion can lose information about the overall magnitude
of the BigInteger value as well as return a result with the opposite
sign.
However, I am not sure it is guaranteed to work as I intended.
Will BigInteger(string).longValue() be enough for my purpose where string is the string representation of the original integer?
Update: I am using JDK 1.7, so Long.parseUnsignedLong() is not available.
In this case, I would just run the code and see what happens.
println(new BigInteger("2").pow(63).longValue());
println(new BigInteger("2").pow(63).subtract(new BigInteger("1")).longValue());
println(new BigInteger("2").pow(64).longValue());
println(new BigInteger("2").pow(64).subtract(new BigInteger("1")).longValue());
Outputs
-9223372036854775808
9223372036854775807
0
-1
So yes, BigInteger.longValue() does exactly what you think it does (and according to the reading of the docs, this is the guaranteed behavior. AKA, it is converted to a bit array, and only the low 64 bits are kept and used as long value, ignoring the fact that the 64'th bit is actually the sign bit).
You should use unsigned long methods in Long class.
String s = "18446744073709551615"; // 2^64 - 1
long value = Long.parseUnsignedLong(s);
System.out.println("long value = " + value);
System.out.println("unsigned long value = " + Long.toUnsignedString(value));
result
long value = -1
unsigned long value = 18446744073709551615
Referring to page number 79 of " Java The complete Reference" 7th edition by Herbert Schildt.
The author says : " If the integer’s value is larger than the range of a
byte, it will be reduced modulo (the remainder of an integer division by the) byte’s range".
The range of byte in java is -128 to 127. So the maximum value that fits in a byte is 128. If an integer value is assigned to a byte as shown below :
int i = 257;
byte b;
b = (byte) i;
Since 257 crosses the range 127, 257 % 127 = 3 should be stored in 'b'.
But am getting the output as 1 instead of 3.
Where have I gone wrong in understanding the concept?
Just consider the binary representation of the numbers :
257 is represented in binary as 00000000 00000000 00000001 00000001
When you cast this 32 bits int to an 8 bits byte, you keep only the lowest 8 bits :
00000001
which is 1
257 = 00000000 000000000 00000001 00000001 in bits and a byte is made up of 8 bits only...
As a result only the lower 8 bits are stored and 1 is the output.
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.
I need some help with bitwise operations.
I have number(64 bit) were first 16 bits are meaningful, and I'd like to set rest of them to "1"
00000000 11000001 00000000 00000000 ... <- currrent value
00000000 11000001 11111111 11111111 ... <- result I am trying to achieve
P.S. Oh, yeah! Sometimes, to solve - you just need to write out your task:)
I got it: value |= (-1 << bitsCount);
bitsCount - count of my meaningful bits
Use the bitwise OR operator:
value |= 0xFFFF
11111111111111112 = 216 - 1= FFFF16
OR it with 11111111 11111111. foo | 0xffff
If I have an byte value 00101011 and I want to represent it as int value I have: 00000000000000000000000000101011, what seems to be clear for me. Bu I have problem with byte value 11010100 which as int is represented by 11111111111111111111111111010100. I don't know where it came from. Can someone explain me the idea of extension byte value to int?
The byte value 11010100 represents a negative number (-44), because the most significant bit is set. When this undergoes primitive widening conversion, it must still represent the same negative value in the two's complement representation. This done using sign extension. That means that all new bits are the same as the original sign bit.
11010100 => -44
11111111 11111111 11111111 11010100 => -44
If this did not occur, then the sign bit would no longer be a sign bit, and it would be interpreted "normally", and the value would no longer be the same.
00000000 00000000 00000000 11010100 => 212