Memory allocation for byte value upon shifting - java

I wrote a small demo for myself for better understanding of shifting a byte values. So I've byte 'd' with value 127:
class Demo {
public static void main (String args[]) {
byte d = 127; // 8-bit is equal to 0 111 1111
and what I try to do is to shift it in a value of 2 to the left:
int e = d << 2; /* 32-bit shifted value is equal to 0 000 0000 0000 0000 0000 0001 1111 1100
0 * 2^0 + 0 * 2^1 + 1 * 2^2 + 1 * 2^3 + 1 * 2^4 + 1 * 2^5 + 1 * 2^6 + 1 * 2^7 + 1 * 2^8 =
0 * 1 + 0 * 2 + 1 * 4 + 1 * 8 + 1 * 16 + 1 * 32 + 1 * 64 + 1 * 128 + 1 * 256 =
0 + 0 + 4 + 8 + 16 + 32 + 64 + 128 + 256 = 508
*/
Please let me know if my logic in comments is correct, cause it's first time for me of doing such a things. So the real question is about memory allocation once I try to cast 'e' back to byte:
byte f = (byte)(e); /* [] indicates 8-bit at 32-bit shifted value: 0 000 0000 0000 0000 0000 0001 [1111 1100]
0 * 2^0 + 0 * 2^1 + 1 * 2^2 + 1 * 2^3 + 1 * 2^4 + 1 * 2^5 + 1 * 2^6 - 1 * 2^7 =
0 * 1 + 0 * 2 + 1 * 4 + 1 * 8 + 1 * 16 + 1 * 32 + 1 * 64 - 1 * 128 =
0 + 0 + 4 + 8 + 16 + 32 + 64 - 128 = -4
*/
int g = (byte)(e);
}
}
both byte 'f' and int 'g' works perfect but the book I'm reading now advice me to use int with a similar conditions without any explanations so the real thing I worry about is 'memory allocation'. Does it really matter which type to use or once byte value is shifted and the memory got expended to 32-bit it's impossible to reduce it back to 8-bit?
Additionally I've a strange question. How can I check the real 'bitness' of any value? Let's say when I execute something like this:
byte a = 10;
System.out.println(Integer.toBinaryString(a));
int b = 10;
System.out.println(Integer.toBinaryString(b));
The result is '1010' in both cases. But if I get it right byte 'a' use 8 bits of memory and int 'b' use 32. But for:
byte c = 5 << 1;
System.out.println(Integer.toBinaryString(c));
Result is '1010' too but now it use 32 bits of memory while byte and short values are promoted to int when an expression is evaluated. How can I 'see' this in real and ensure by myself?

I'm not entirely sure what you are trying to do, but as for the assignment to f and g, both give the same result, since you assign to it (byte) e which fits within a byte variable.
If you would assign without casting, you'll get a diferent result, since the value of e is too large to fit within a byte.
As for the results of toBinaryString, they obviously don't show leading zeroes, which is why you see the same result for a byte variable and an int variable holding the same value. If you want to see all the bits, you'll have to print the leading zeroes yourself, and the number of leading zeroes depend on the type of the variable (so, for a byte variable, you'll have to add leading zeroes to reach a total of 8 bits, for int you'll have to reach 32 bits, etc...).
If you want to see the leading zeroes, you can make you own version of toBinaryString. Looking at an implementation of Integer, I found that toBinaryString calls toUnsignedString :
public static String toBinaryString(int i) {
return toUnsignedString(i, 1);
}
private static String toUnsignedString(int i, int shift) {
char[] buf = new char[32];
int charPos = 32;
int radix = 1 << shift;
int mask = radix - 1;
do {
buf[--charPos] = digits[i & mask];
i >>>= shift;
} while (i != 0);
return new String(buf, charPos, (32 - charPos));
}
As you can see, this method returns only part of the 32 chars that represent the binary value of the int. If you return new String(buf) instead, you'll get the full binary String with leading zeroes.

Related

Java - Why does int default to 0 when a value outside the range is attempted to be stored in it [duplicate]

This question already has answers here:
How does Java handle integer underflows and overflows and how would you check for it?
(12 answers)
Closed 3 years ago.
I have a simple program for calculating the x to the power of y.
public static int calculatePower(int x, int y) {
int result = 1;
if (y == 0)
return result;
for (int i = 1; i <= y; i++) {
result = result * x;
}
return result;
}
When i pass the parameters as 4 and 15, i get the value back as 1073741824. But when the parameters are 4 and 16, the value returned is zero.
If the outer range value cannot be stored in int, shouldnt it be retaining the last value - 1073741824 ?
If the outer range value cannot be stored in int, shouldnt it be retaining the last value - 1073741824 ?
No, it's storing the result of the final operation, following the overflow rules listed in the JLS on each operation.
If an integer multiplication overflows, then the result is the low-order bits of the mathematical product as represented in some sufficiently large two's-complement format. As a result, if overflow occurs, then the sign of the result may not be the same as the sign of the mathematical product of the two operand values.
It's not that the result "defaults" to 0 - it's just that one of the operations ended up overflowing so that the last 32 bits were all 0. All multiplications after that would also result in 0.
You can see that if you add diagnostics to each step:
public class Test {
public static void main(String[] args) {
calculatePower(4, 16);
}
public static int calculatePower(int x, int y) {
int result = 1;
for (int i = 0; i < y; i++) {
System.out.printf("%d * %d = %d%n", result, x, result * x);
result = result * x;
}
return result;
}
}
I've simplified your loop at the same time, which means you don't need the base case condition beforehand. Note that neither your original code nor my version handles negative powers - for production code, you should check that and throw an exception.
Output:
1 * 4 = 4
4 * 4 = 16
16 * 4 = 64
64 * 4 = 256
256 * 4 = 1024
1024 * 4 = 4096
4096 * 4 = 16384
16384 * 4 = 65536
65536 * 4 = 262144
262144 * 4 = 1048576
1048576 * 4 = 4194304
4194304 * 4 = 16777216
16777216 * 4 = 67108864
67108864 * 4 = 268435456
268435456 * 4 = 1073741824
1073741824 * 4 = 0
If you raise it to a greater power, e.g. 20, you'll see lines of "0 * 4 = 0" at the end.
1073741824 + 1 gives you a value -1073741824 because of overflow.
4 and 15 are basically 2^16.
4 and 16 are basically 2^17
2^17 is the double of the 2^ 16. thats why it turns into 1 and all 16 bits are zero. So, all 16 lower bits wiil be picked..
It doesn't default to 0. Your calculation just overflows and ends up in the dead center of the integer range.

Maximum number of consecutive 1 in a given number

public int tobinary(int x)
{
int count = 0;
while(x!=0)
{
x=(x&(x<<1)); //how this stuff is working
count++;
}
return count;
}
the above code is working fine but actually i did copy and paste.so i just want to know how that line of code which i mentioned above is working.it would be a great help for me.
for example i am giving i/p as 7 the binary format for this is 0111 so our answer will be 3 but how ?
As we know, the << operator shifts all bits in its operand to the left, here by 1. Also, the & operator performs a bitwise-and on all bits of both its operands.
When will x not be 0? When the bitwise-and operation finds 2 bits that are both set in both operands. The only time that this will be true is when there are 2 or more consecutive 1 bits in x and x << 1.
x : 0000 0111
x << 1: 0000 1110
-----------------
&: 0000 0110
count = 1
If it's not 0, then there are at least 2 consecutive 1 bits in the number, and the (maximum) number of consecutive 1 bits in the number has been reduced by 1. Because we entered the loop in the first place, count it and try again. Eventually there won't be any more consecutive 1 bits, so we exit the loop with the correct count.
x : 0000 0110
x << 1: 0000 1100
-----------------
&: 0000 0100
count = 2
x : 0000 0100
x << 1: 0000 1000
-----------------
&: 0000 0000
count = 3, exit loop and return.
x = (x & (x << 1)) is performed enough times to eliminate the longest consecutive groups of 1 bits. Each loop iteration reduces each consecutive group of 1s by one because the number is logically ANDed with itself shifted left by one bit. This continues until no consecutive group of 1s remains.
To illustrate it for number 110111101:
110111101 // initial x, longest sequence 4
1101111010 // x << 1, count 1
100111000 // new x, longest sequence 3
1001110000 // x << 1, count 2
110000 // new x, longest sequence 2
1100000 // x << 1, count 3
100000 // new x, longest sequence 1
1000000 // x << 1, count 4
0 // new x, end of loop
Do note that since Java 7 it's handy to declare binary literals with int input = 0b110111101.
<< (left shift) : Binary Left Shift Operator. The left operands value is moved left by the number of bits specified by the right operand.
i.e. x<<1 shifts the value bit from right to left by 1 and in the unit position add 0. So, lets say for x=7, bit representation will be 111. Performing x << 1 will return 110 i.e. discarded the head element, shifted the bits to left and added 0 in the end.
This while loop can be broken down into below iteration for initial value of x=7
iteration 1) 111 & 110 =110
iteration 2) 110 & 100 =100
iteration 3) 100 & 000 =000
As value of x is 0, no more iteration
Hope this explains the behaviour of this code. You can put System.out.println(Integer.toBinaryString(x)); to see the change in bit value of x yourself
So what happens is, for each iteration in the while loop,
x = x (AND operator) (2 * x).
For example, when x = 7
count = 0
Iteration 1:
//x = 7 & 14 which results in 6 ie
0111
1110 (AND)
-------
0110 => 6
-------
count = 1
Iteration 2:
//x = 6 & 12 results in 4
0110
1100 AND
-------
0100 => 4
-------
count = 2
Iteration 3:
// x = 4 & 8 results in 0
0100
1000 AND
-----
0000
-----
count = 3
That's how you get 3 for 7

Split IP octet bytes

I had to split IP address bytes and preserve them in a tree. Here what I've implemented, but I've the feeling that there is a faster way to achieve the same goal. So if you have any ideas, please let me know :)
private static final int MAX_IP_BITS_SIZE = 16 * Byte.SIZE;
/**
* Splits octet bytes in new byte array based on the splitter size.
*
* #param bytes address representation of IPv4 or IPv6 to be split.
* #param splitSize is the amount of bit to split on. It could be from 1 to 7, otherwise returns unsplit bytes.
* #return byte[] split version of the address bytes.
*/
private byte[] splitAddressBytes(byte[] bytes, final int splitSize)
{
if (splitSize < 1 || splitSize > 7)
{
return bytes;
}
int byteIndex = 0;
int changeByteIndex = 0;
byte[] octetBytes = new byte[MAX_IP_BITS_SIZE];
for (int i = 0; i < Byte.SIZE * bytes.length; i++)
{
/*
* Get byte index based on the splitter size, e.g. if the splitter size is 3, which mean that 'i % Byte.SIZE / splitSize' will
* vary from 0 to 2, i.e. on each change between those value means we can move to the next index.
*/
int inputBitIndex = i % Byte.SIZE;
if (changeByteIndex != inputBitIndex / splitSize)
{
changeByteIndex = inputBitIndex / splitSize;
byteIndex++;
}
/*
* Traverse all bits one by one and check if it is set to 1, if so add it to the result byte. Get the bit at the position
* "i / Byte.SIZE", then shift each bit at the first position and check if it is 1 or 0, i.e. i % Byte.SIZE is the position of
* the bit that we want to check (0,1,2,3,4,5,6,7), e.g. 128 is 1000 0000 and i % Byte.SIZE when i=0 is 0, as and i % Byte.SIZE
* is 0, then do not shift, just AND 1000 0000 and 0x80 (which is 128 or 1000 0000). In that case the result is 128, which is
* not 0 so the bit at that position is 1. Second attempt i=1, so i / Byte.SIZE = 0 and i % Byte.SIZE = 1. In that case we want
* to check second bit which is 1000 0000 << 1 = 0000 0000, from where 0000 0000 & 1000 0000 = 0, so the bit at that position is
* 0.
*/
if ((bytes[i / Byte.SIZE] << inputBitIndex & 0x80) != 0)
{
/*
* Now when we know that bit at that position (i) is set to 1 we have to place it to the particular byte at the desired
* position based on the splitter size, i.e. 'octetBytes[byteIndex] & 0xFF' - get current value of the bit based on the
* index (which also take into account split size) and apply bitwise OR with the bit that is set to 1 based on the bit
* shift. So to determine the index position of the bit: '(Byte.SIZE - splitSize)' - get offset or the starting point from
* the byte based on the splitter size. 'inputBitIndex % splitSize' - get which bit has to be set to 1, i.e. in case of
* splitter set to 3 the block size is 3 and that will result in 0,1, or 2. '(Byte.SIZE - splitSize) + (inputBitIndex %
* splitSize))' - combining offset and bit position we have the final bit position where we have to place the bit with value
* 1. So with bit shift of 0x80 at that position, e.g. 1000 0000 >>> 5 = 0000 0100 we have the desired byte to add to
* already existing. e.g. current byte is 0000 0000 and we want to add 1 at the correct position, 0000 0000 | 0x80 (which is
* 128 or 1000 0000) >>> 5, where 5 is the bit position from 5 trough 7 in case of splitter size 3. e.g. 0000 0000 | 0000
* 0100 = 0000 0100.
*/
octetBytes[byteIndex] = (byte)(octetBytes[byteIndex] & 0xFF | (0x80 >>> (Byte.SIZE - splitSize) + (inputBitIndex % splitSize)));
}
}

Java Signed Right Shift

I have seen this in a java code.
int n = 300 //passed through a function
size = (n + 31) >> 5 //size = 10
what could be the significance of 5?
What is the significance of 31 //should something to do with int size (31 bit + 1 sign)
Thanks
The significance of 5 is that 32 = 2^5.
size = (n + 31) >> 5
sets size to ceiling(n/32), which is the number of 32-bit integers needed to store n bit flags.
The addition of 31 to n is to make sure that the dividend is at least as large as the smallest multiple of 32 greater than or equal to n.

(Java) Specify number of bits (length) when converting binary number to string?

I'm trying to store a number as a binary string in an array but I need to specify how many bits to store it as.
For example, if I need to store 0 with two bits I need a string "00". Or 1010 with 6 bits so "001010".
Can anyone help?
EDIT: Thanks guys, as I'm rubbish at maths/programming in general I've gone with the simplest solution which was David's. Something like:
binaryString.append(Integer.toBinaryString(binaryNumber));
for(int n=binaryString.length(); n<numberOfBits; n++) {
binaryString.insert(0, "0");
}
It seems to work fine, so unless it's very inefficient I'll go with it.
Use Integer.toBinaryString() then check the string length and prepend it with as many zeros as you need to make your desired length.
Forget about home-made solutions. Use standard BigInteger instead. You can specify number of bits and then use toString(int radix) method to recover what you need (I assume you need radix=2).
EDIT: I would leave bit control to BigInteger. The object will internally resize its bit buffer to fit the new number dimension. Moreover arithmetic operations can be carried out by means of this object (you do not have to implement binary adders/multipliers etc.). Here is a basic example:
package test;
import java.math.BigInteger;
public class TestBigInteger
{
public static void main(String[] args)
{
String value = "1010";
BigInteger bi = new BigInteger(value,2);
// Arithmetic operations
System.out.println("Output: " + bi.toString(2));
bi = bi.add(bi); // 10 + 10
System.out.println("Output: " + bi.toString(2));
bi = bi.multiply(bi); // 20 * 20
System.out.println("Output: " + bi.toString(2));
/*
* Padded to the next event number of bits
*/
System.out.println("Padded Output: " + pad(bi.toString(2), bi.bitLength() + bi.bitLength() % 2));
}
static String pad(String s, int numDigits)
{
StringBuffer sb = new StringBuffer(s);
int numZeros = numDigits - s.length();
while(numZeros-- > 0) {
sb.insert(0, "0");
}
return sb.toString();
}
}
This is a common homework problem. There's a cool loop that you can write that will compute the smallest power of 2 >= your target number n.
Since it's a power of 2, the base 2 logarithm is the number of bits. But the Java math library only offers natural logarithm.
math.log( n ) / math.log(2.0)
is the number of bits.
Even simpler:
String binAddr = Integer.toBinaryString(Integer.parseInt(hexAddr, 16));
String.format("%032", new BigInteger(binAddr));
The idea here is to parse the string back in as a decimal number temporarily (one that just so happens to consist of all 1's and 0's) and then use String.format().
Note that you basically have to use BigInteger, because binary strings quickly overflow Integer and Long resulting in NumberFormatExceptions if you try to use Integer.fromString() or Long.fromString().
Try this:
String binaryString = String.format("%"+Integer.toString(size)+"s",Integer.toBinaryString(19)).replace(" ","0");
where size can be any number the user wants
Here's a simple solution for int values; it should be obvious how to extend it to e.g. byte, etc.
public static String bitString(int i, int len) {
len = Math.min(32, Math.max(len, 1));
char[] cs = new char[len];
for (int j = len - 1, b = 1; 0 <= j; --j, b <<= 1) {
cs[j] = ((i & b) == 0) ? '0' : '1';
}
return new String(cs);
}
Here is the output from a set of sample test cases:
0 1 0 0
0 -1 0 0
0 40 00000000000000000000000000000000 00000000000000000000000000000000
13 1 1 1
13 2 01 01
13 3 101 101
13 4 1101 1101
13 5 01101 01101
-13 1 1 1
-13 2 11 11
-13 3 011 011
-13 4 0011 0011
-13 5 10011 10011
-13 -1 1 1
-13 40 11111111111111111111111111110011 11111111111111111111111111110011
Of course, you're on your own to make the length parameter adequate to represent the entire value.
import java.util.BitSet;
public class StringifyByte {
public static void main(String[] args) {
byte myByte = (byte) 0x00;
int length = 2;
System.out.println("myByte: 0x" + String.valueOf(myByte));
System.out.println("bitString: " + stringifyByte(myByte, length));
myByte = (byte) 0x0a;
length = 6;
System.out.println("myByte: 0x" + String.valueOf(myByte));
System.out.println("bitString: " + stringifyByte(myByte, length));
}
public static String stringifyByte(byte b, int len) {
StringBuffer bitStr = new StringBuffer(len);
BitSet bits = new BitSet(len);
for (int i = 0; i < len; i++)
{
bits.set (i, (b & 1) == 1);
if (bits.get(i)) bitStr.append("1"); else bitStr.append("0");
b >>= 1;
}
return reverseIt(bitStr.toString());
}
public static String reverseIt(String source) {
int i, len = source.length();
StringBuffer dest = new StringBuffer(len);
for (i = (len - 1); i >= 0; i--)
dest.append(source.charAt(i));
return dest.toString();
}
}
Output:
myByte: 0x0
bitString: 00
myByte: 0x10
bitString: 001010
So here instead of 8 you can write your desired length and it will append zeros accordingly. If the length of your mentioned integer exceeds that of the number mentioned then it will not append any zeros
String.format("%08d",1111);
Output:00001111
String.format("%02d",1111);
output:1111

Categories

Resources