So, i'm fairly new to java, and i'm a bit confused about the byte system. So I made this program that converts integers to their base two value.
class Bits
{
public static void main(String[] args)
{
byte a;
a = 5;
System.out.println(Integer.toBinaryString(a)); /* prints 101 */
a = -1;
System.out.println(Integer.toBinaryString(a)); /* prints
11111111111111111111111111111111*/
}
}
It works as expected with positive numbers, but when I enter negative numbers, it gets weird. Now I know what two's compliment is, and it doesn't say that -1 is 11111111111111111111111111111111. It is supposed to be 11111111, right? When I change a to an int 255, which would be -1 as a byte, I get the normal result, 11111111, when I switch it to binary. Can someone explain to me why this is happening, or did I do something wrong. (I am using java 8 and i'm on a mac)
Integer.toBinaryString accepts an int as an argument. So a is casted from byte to int before being passed to the method. And yes the two's complement of -1 of a 32 bits integer is 11111111111111111111111111111111.
You should try with Integer.toBinaryString(a & 0xFF). So that a is widened to 32 bits, but then 24 most relevant bits are discarded through masking. The bit sign is kept since you were starting from a byte so the result will be correct.
You can verify it by converting the truncating the int converted from a and the parse it as an int and converting it back to a byte:
int counter = 0;
for (byte a = -128; counter <= 256; ++a, ++counter)
{
byte b = (byte)(Integer.valueOf(Integer.toBinaryString(a & 0xFF), 2) & 0xFF);
System.out.println(a+" == "+b);
}
Related
A byte is the smallest numeric datatype java offers but yesterday I came in contact with bytestreams for the first time and at the beginning of every package a marker byte is send which gives further instructions on how to handle the package. Every bit of the byte has a specific meaning so I am in need to entangle the byte into it's 8 bits.
You probably could convert the byte to a boolean array or create a switch for every case but that can't certainly be the best practice.
How is this possible in java why are there no bit datatypes in java?
Because there is no bit data type that exists on the physical computer. The smallest allotment you can allocate on most modern computers is a byte which is also known as an octet or 8 bits. When you display a single bit you are really just pulling that first bit out of the byte with arithmetic and adding it to a new byte which still is using an 8 bit space. If you want to put bit data inside of a byte you can but it will be stored as a at least a single byte no matter what programming language you use.
You could load the byte into a BitSet. This abstraction hides the gory details of manipulating single bits.
import java.util.BitSet;
public class Bits {
public static void main(String[] args) {
byte[] b = new byte[]{10};
BitSet bitset = BitSet.valueOf(b);
System.out.println("Length of bitset = " + bitset.length());
for (int i=0; i<bitset.length(); ++i) {
System.out.println("bit " + i + ": " + bitset.get(i));
}
}
}
$ java Bits
Length of bitset = 4
bit 0: false
bit 1: true
bit 2: false
bit 3: true
You can ask for any bit, but the length tells you that all the bits past length() - 1 are set to 0 (false):
System.out.println("bit 75: " + bitset.get(75));
bit 75: false
Have a look at java.util.BitSet.
You might use it to interpret the byte read and can use the get method to check whether a specific bit is set like this:
byte b = stream.read();
final BitSet bitSet = BitSet.valueOf(new byte[]{b});
if (bitSet.get(2)) {
state.activateComponentA();
} else {
state.deactivateComponentA();
}
state.setFeatureBTo(bitSet.get(1));
On the other hand, you can create your own bitmask easily and convert it to a byte array (or just byte) afterwards:
final BitSet output = BitSet.valueOf(ByteBuffer.allocate(1));
output.set(3, state.isComponentXActivated());
if (state.isY){
output.set(4);
}
final byte w = output.toByteArray()[0];
How is this possible in java why are there no bit datatypes in java?
There are no bit data types in most languages. And most CPU instruction sets have few (if any) instructions dedicated to adressing single bits. You can think of the lack of these as a trade-off between (language or CPU) complexity and need.
Manipulating a single bit can be though of as a special case of manipulating multiple bits; and languages as well as CPU's are equipped for the latter.
Very common operations like testing, setting, clearing, inverting as well as exclusive or are all supported on the integer primitive types (byte, short/char, int, long), operating on all bits of the type at once. By chosing the parameters appropiately you can select which bits to operate on.
If you think about it, a byte array is a bit array where the bits are grouped in packages of 8. Adressing a single bit in the array is relatively simple using logical operators (AND &, OR |, XOR ^ and NOT ~).
For example, testing if bit N is set in a byte can be done using a logical AND with a mask where only the bit to be tested is set:
public boolean testBit(byte b, int n) {
int mask = 1 << n; // equivalent of 2 to the nth power
return (b & mask) != 0;
}
Extending this to a byte array is no magic either, each byte consists of 8 bits, so the byte index is simply the bit number divided by 8, and the bit number inside that byte is the remainder (modulo 8):
public boolean testBit(byte[] array, int n) {
int index = n >>> 3; // divide by 8
int mask = 1 << (n & 7); // n modulo 8
return (array[index] & mask) != 0;
}
Here is a sample, I hope useful for you!
DatagramSocket socket = new DatagramSocket(6160, InetAddress.getByName("0.0.0.0"));
socket.setBroadcast(true);
while (true) {
byte[] recvBuf = new byte[26];
DatagramPacket packet = new DatagramPacket(recvBuf, recvBuf.length);
socket.receive(packet);
String bitArray = toBitArray(recvBuf);
System.out.println(Integer.parseInt(bitArray.substring(0, 8), 2)); // convert first byte binary to decimal
System.out.println(Integer.parseInt(bitArray.substring(8, 16), 2)); // convert second byte binary to decimal
}
public static String toBitArray(byte[] byteArray) {
StringBuilder sb = new StringBuilder();
for (int i = 0; i < byteArray.length; i++) {
sb.append(String.format("%8s", Integer.toBinaryString(byteArray[i] & 0xFF)).replace(' ', '0'));
}
return sb.toString();
}
I have written the following program in Java to convert long to byte.
public class LongtoByte
{
public static void main(String[] args)
{
long a=222;
byte b=(byte)(a & 0xff);
System.out.println("the value of b is" +b);
}
}
The problem is I get the result -34 for the variable b.
Please tell me how to get the correct value. I want the value in bytes only.
Java's types are signed, bytes allow numbers between −128 and +127.this is the reason you were getting −34 for 222 value
long a=121;
byte b=(byte)(a );
System.out.println("the value of b is" +b);
All integer types (including byte) are signed in Java, so if you stick 222 into a Java byte you get an overflow (resulting in the negative number you saw). If you need the range 0–255 for a integral number in Java you'll need at least a short.
However, if you're just going to write that result somewhere as a single byte you don't need to worry, as its bit pattern representation is exactly the same as 222 in an unsigned byte.
You can use the java.lang.Long class' byteValue() method:
byte b = a.byteValue();
You will have to make a Long type object as such:
Long a = new Long(222);
And as others have noted, this will return -34 due to overflow of the range that can be represented by a byte which is 8 bits.
When you print a byte it assumes a range of -128 to 127.
If you print
byte b = (byte) 222;
you should expect to get a negative number.
If you want to store the range 0 to 255 you need to convert it when you get the value out.
int i = 222;
byte[] b = { (byte) i };
int i2 = b[0] & 0xFF; // give me the original unsigned 0 to 255.
assert i == i2;
You can invent all sorts of encoding. e.g. Say you want to store numbers which are only in millions say 0 to 200 million or decimal numbers -1.00 to 1.00 in a byte. You might first think this is impossible because a byte only stores 8 bits.
// store millions.
byte b = (byte) (i / 1000000);
int i = (b & 0xff) * 1000000;
// store decimal from -1.00 to 1.00
byte b = (byte) Math.round(d * 100);
double d = b / 100.0;
public class LongtoByte
{
public static void main(String[] args)
{
long a=222;
byte b=(byte)(a);
System.out.println("the value of b is" +b);
}
}
This byte bValue = (byte) num; statement is converted into a byte format.
To convert an int into a byte array, I'm using the following code:
int a = 128;
byte[] b = convertIntValueToByteArray(a);
private static byte[] convertIntValueToByteArray(int intValue){
BigInteger bigInteger = BigInteger.valueOf(intValue);
byte[] origByteArray = bigInteger.toByteArray();
byte[] noSignByteArray = new byte[bigInteger.bitLength()/8];
if(bigInteger.bitLength()%8!=0){
noSignByteArray = origByteArray;
}else{
System.arraycopy(origByteArray,1,noSignByteArray,0,noSignByteArray.length);
}
return noSignByteArray;
}
There are two things which I'm attempting to do.
1)I need to know the number of bytes (rounded up to the closes byte) of the original integer. However, I don't need the additional bit that is added for the sign bit when I call the toByteArray() method. This is the reason why I have the helper method. So in this example, if I don't have the helper method, when I convert 128 to a byte array I get the length to be 2 octets because of the sign bit but I'm only expecting it to be one octet.
2)I need the positive representation of the number. In this example, if I attempt to print the first element in array b, I get -128. However, the numbers I will be using will be positive numbers only so what I actually want is 128. I'm limited to using a byte array. Is there a way to accomplish this?
Updated Post
Thank you for the responses. I haven't found the exact answer I was looking for so I'll attempt to give more details. Ultimately, I want to write values of different types over a data output stream. In this post, I'd like to clarify what happens when ints are written to a data output stream. I've come across two scenarios.
1)
DataOutputStream os = new DataOutputStream(this.socket.getOutputStream());
byte[] b = BigInteger.valueOf(128).toByteArray();
os.write(b);
2)
DataOutputStream os = new DataOutputStream(this.socket.getOutputStream());
os.write(128);
In the first scenario, when the bytes are read from a data input stream, it seems that the first element in the byte array is a 0 to represent the msb and the second element in the array contains the number -128. However, since the msb is 0 we would be able to determine that it is intended to be a positive number. In the second scenario, there is no msb and the only element present in the byte array read from the input stream is -128. I was expecting the write() method of the data output stream to convert the int into the byte array in the same manner as the toByteArray() method does on a BigInteger object. However, this doesn't seem to be the case as the msb is not present. So my question is, how in the second scenario are we supposed to know that 128 is supposed to be a positive number and not a negative one if there is no msb.
As you probably already know
In an octet, the pattern 10000000 can be interpreted as either 128 or -128, depending on the, um, outside interpretation
Java's byte type interprets octects as values in -128...127 only.
If you are building an application in which the entire world consists of nonnegative integers only, then you could simply do all of your work under the assumption that the byte value -128 will mean 128 and -127 will mean 129 and ... and -1 will mean 255. This is certainly doable but it takes work.
Dealing with the notion of an "unsigned byte" like this is normally done by expanding the byte into a short or int with the higher order bits all set to zero and then performing arithmetic or displaying your values. You will need to decide whether such an approach is more to your liking than just representing 128 as two octets in your array.
I think the following code might be sufficient.
In java int is a twos-complements binary number:
-1 = 111...111
ones complement = 000...000; + 1 =
1 = 000...001
So that about the sign bit I do not understand. Be it, that you could do Math.abs(n).
A byte ranges from -128 to 127, but the interpretation is a matter of masking, as below.
public static void main(String[] args) {
int n = 128;
byte[] bytes = intToFlexBytes(n);
for (byte b: bytes)
System.out.println("byte " + (((int)b) & 0xFF));
}
public static byte[] intToFlexBytes(int n) {
// Convert int to byte[4], via a ByteBuffer:
byte[] bytes = new byte[4];
ByteBuffer bb = ByteBuffer.allocateDirect(4);
bb.asIntBuffer().put(n);
bb.position(0);
bb.get(bytes);
// Leading bytes with 0:
int i = 0;
while (i < 4 && bytes[i] == 0)
++i;
// Shorten bytes array if needed:
if (i != 0) {
byte[] shortenedBytes = new byte[4 - i];
for (int j = i; j < 4; ++j) {
shortenedBytes[j - i] = bytes[j]; // System.arrayCopy not needed.
}
bytes = shortenedBytes;
}
return bytes;
}
To answer your first question—how many bytes are required to represent a nonnegative integer using an unsigned representation—consider the following functions I wrote in Common Lisp.
(defconstant +bits-per-byte+ 8)
(defun bit-length (n)
(check-type n (integer 0) "a nonnegative integer")
(if (zerop n)
1
(1+ (floor (log n 2)))))
(defun bytes-for-bits (n)
(check-type n (integer 1) "a positive integer")
(values (ceiling n +bits-per-byte+)))
These highlight the mathematical underpinnings of the problem: namely, the logarithm tells you how many powers of two (as provided by bits) it takes to dominate a given nonnegative integer, adjusted to be a step function with floor, and the number of bytes it takes to hold that number of bits again as a step function, this time adjusted with ceiling.
Note that the number zero is intolerable as input to a logarithm function, so we avoid it explicitly. You may observe that the bit-length function could also be written with a slight transformation of the core expression:
(defun bit-length-alt (n)
(check-type n (integer 0) "a nonnegative integer")
(values (ceiling (log (1+ n) 2))))
Unfortunately, as the logarithm of one is always zero, regardless of the base, this version says that the integer zero can be represented by zero bits, which isn't the answer we want.
For your second goal, you can use the functions I've defined above to allocate the required number of bytes, and incrementally set the bits you need, ignoring sign. It's hard to tell if you're having trouble getting the proper bits set in the byte vector, or whether your problem is in interpreting the bits in way that avoids treating the high bit as a sign bit (that is, two's complement representation). Please elaborate what kind of push you need to get you moving again.
I am really short on time for doing the learning of bitwise operations.
I want to convert large integer(>127) values without doing '<<' or anything similar.
I need byte representation of integer values used to identify sequence numbers of packets in header sent across UDP. If there is no solution I will introduce two bytes..
Something like: 1, 1 ; 1,2 ; 1,3 ; packet lost ; 1,4 ; packet lost; 2,1 ,2,2
and then reset it upon reaching 127; 127
I can introduce third, but this is rather ugly.
It would be really useful to have black box that is part of java api doing all that byte conversion for me. Is there?
Thanks,
To pack an unsigned 8-bit value into a byte:
static byte toByte(int i) {
if ((i < 0) || (i > 255))
throw new IllegalArgumentException(String.valueOf(i));
return (byte) i;
}
To convert back:
static int toInt(byte b) {
return (b < 0) ? (b + 256) : b;
}
After reading your comments on other answers, it sounds like you might want something like this:
byte[] b = BigInteger.valueOf(counter).toByteArray();
and
long counter = new BigInteger(b).longValue();
Since the length of the array would vary as the counter grows, you'd need some way to indicate its length or delimit it. But this technique will convert any integer value to an array of bytes.
Is the problem that you want unsigned bytes, as in, numbers between 128 and 255 inclusive?
That's...tricky. The Java language won't let you directly treat bytes as unsigned...but with library support it gets a little easier. Guava provides an UnsignedBytes utility class for some of these needs. Addition, multiplication, and subtraction are all exactly the same on signed and unsigned bytes.
EDIT: Judging from your additional comments, you might be interested in Ints.toByteArray(int) and the like, which work on types between byte and BigInteger.
According to my understanding, you want to separate an int into 4 bytes. If so, then just copy paste this code:
int i = /* your int */
int[] b = { (i >> 24) & 0xff, (i >> 16) & 0xff, (i >> 8) & 0xff, i & 0xff };
Indices 0-3 are each of the 4 bytes in the int.
I have the following c code which id like to port to Java
unsigned long long* data=(unsigned long long*)pBuffer; // file data
unsigned long long crypt = 0x0000;
unsigned long long next_crypt;
unsigned int len = size >> 3;
for(unsigned int i=0; i<len;i++) {
next_crypt = crypt+data[i]-0xCAFEBABE;
data[i] = ((data[i]<<0x1d)|(data[i]>>0x23))+0xCAFEBABE;
data[i] = (data[i]<<0x0e)|(data[i]>>0x32);
data[i] = data[i] - crypt;
crypt = next_crypt;
}
I tried to port this to java using long, however this would result in negative values. Therefor i switched to biginteger since i have to do arithmetics (bit shifting etc).
I got the desired 64bit unsigned long value using BigInteger, however when i wanted to convert it to byte (BigInteger.toByteArray) it was 14 bytes long and no longer 8 bytes - so i cannot modify my array/file anymore. I tried using toLongValue() but the data was incorrect.
Thanks
Your C code is relying on bits being shifted off the high-order end of the unsigned long long. (These are rotated around to the other end by the other shift.) BigInteger is arbitrary precision and hence has no end, so left-shifted bits are never shifted off.
You could construct a 64-bit BigInteger bitwise AND mask and AND it after the left shifts. This is an intuitive solution.
You could also just simply ignore the high-order bytes.
byte[] bar = foo.toByteArray();
if (bar.length > 8) {
bar = System.arrayCopy(bar, bar.length - 8, new byte[8], 0, 8);
}
If len is large, then this simple solution would be wasteful of memory.
In any case there is a saner and higher-performing solution. Java's signed integer types are all guaranteed to have two's complement semantics. The bit semantics for arithmetic with two's complement integers and unsigned integers are identical--the difference is only in the interpretation of the value! So just use the original C code (substituting in Java's long) and at the end, interpret them your way.
byte[] longToByteArray(long x) {
byte[] array = new byte[8];
for (int i = 7; i >= 0; i--) {
array[i] = (byte)x;
x >>>= 8;
}
}
By the way, be sure you replace the >> operator in the C code with Java's >>> operator.
The nice thing about Java is that it's guaranteed to be twos-complement, so provided you use >>> instead of >> and avoid % and / and inequalities, arithmetic is effectively unsigned anyway.