There are many solutions on this page that represent a native Java byte
as a full array of numeric one and zero values. In other words, a single single byte
(with 8 bits) is represented as an entire array of 8 individual numeric values (where each index in the array is a byte itself that represents the 1 or 0 value of each bit position).
That means for a given input byte
(8 bits), an 8 byte array (64 bits) is used to represent ones and zeros. Consequently, an input byte array of length 4 (e.g. representing an int
or unsigned int
), would require 32 bytes (256 bits), and an input byte array of length 8 (e.g. for a long
) would require 64 bytes (512 bits), and so on.
Thats exponential (O(nc)
) complexity - a relatively massive memory/performance expense to do something that the language already supports natively and efficiently. And if there are more than one of these byte array values to work with, that compounds the performance hit further.
The following is a correct (and working) solution if you have a standard byte array representing a single contiguous big-endian bit string and you want to increment it by one bit. It is nearly identical to Cristof R's solution, except that particular solution does not compile.
The following solution is most efficient if you don't need to create a copy of the input byte array, and is useful as an equivalent for iterator incrementation, e.g. i = i + 1
scenarios:
/**
* Treats the specified byte array as a single contiguous big-endian
* bit string, and increments it by a single bit. Does not throw an
* exception on overflow and instead 'rolls' over to zero.
*/
public static void increment(byte[] a) {
for (int i = a.length - 1; i >= 0; --i) {
if (++a[i] != 0) {
break;
}
}
}
If you don't want to modify the source bit string, you can just clone it before incrementing:
byte[] original = new byte[]{0, 0, 0, 0}; //integer value 0
byte[] copy = original.clone();
increment(copy);
Here's a little test program demonstrating:
public class IncrementBitExample {
/**
* Treats the specified byte array as a single contiguous big-endian
* bit string, and increments it by a single bit. Does not throw an
* exception on overflow and instead 'rolls' over to zero.
*/
public static void increment(byte[] a) {
for (int i = a.length - 1; i >= 0; --i) {
if (++a[i] != 0) {
break;
}
}
}
public static String toBinary(byte b) {
String bString = Integer.toBinaryString(b & 0xFF);
return String.format("%8s", bString).replace(' ', '0');
}
public static String toBinary(byte[] bytes) {
StringBuilder sb = new StringBuilder(16);
for(byte b : bytes) {
if (sb.length() > 0) {
sb.append(' '); //separate byte segments for readability
}
String val = toBinary(b);
sb.append(val);
}
return sb.toString();
}
public static void main(String[] args) {
byte[] b = new byte[]{0, 0, 0, 0}; // integer 0
for(int i = 0; i <= 256; i++) {
System.out.println("b: " + toBinary(b));
increment(b); // effectively b = b + 1;
}
}
}
Running main
shows the following output (snipped for brevity):
b: 00000000 00000000 00000000 00000000
b: 00000000 00000000 00000000 00000001
b: 00000000 00000000 00000000 00000010
b: 00000000 00000000 00000000 00000011
b: 00000000 00000000 00000000 00000100
b: 00000000 00000000 00000000 00000101
b: 00000000 00000000 00000000 00000110
b: 00000000 00000000 00000000 00000111
b: 00000000 00000000 00000000 00001000
b: 00000000 00000000 00000000 00001001
b: 00000000 00000000 00000000 00001010
b: 00000000 00000000 00000000 00001011
b: 00000000 00000000 00000000 00001100
b: 00000000 00000000 00000000 00001101
b: 00000000 00000000 00000000 00001110
b: 00000000 00000000 00000000 00001111
b: 00000000 00000000 00000000 00010000
... continued ...
b: 00000000 00000000 00000000 11111110
b: 00000000 00000000 00000000 11111111
b: 00000000 00000000 00000001 00000000
Notice the very last printed bit string. The loop iterator max value is 256
and that number cannot be represented as a single unsigned byte - it requires at least two bytes to represent. As a result, the incrementing of the 2nd-to-last bit string value of:
00000000 00000000 00000000 11111111
(integer value 255
)
has to 'overflow' to the next byte to the left (big-endian), and produces the final value:
00000000 00000000 00000001 00000000
(integer value 256
)