how to assign negative numbers as binary to int variable in java? - java

I was seeing how to represent binary numbers in java.
one option is to use as String and use Integer.parseInt() to get the decimal value;
The other option (assignment of 2 to b):
int b = 0b0010; //2
System.out.println(b);
System.out.println(Integer.toBinaryString(-2));
output:
2
11111111111111111111111111111110
using this format, how to represent -2:
int c=??//-b

int values are stored in 32 bits where the most significant bit is the sign.
0b0010; //2
is actually
0b00000000_00000000_00000000_00000010; //2
To convert that to a negative number, you flip the 0s to 1s and the 1s to 0s` and add 1. So
0b00000000_00000000_00000000_00000010; //2
0b11111111_11111111_11111111_11111101
0b11111111_11111111_11111111_11111110; // +1
And so
int b = 0b11111111_11111111_11111111_11111110;
would have the value -2.

Use the Bitwise NOT operator:
00000000000000000000000000000010 // 2 = 0b0010
00000000000000000000000000000001 // 1 = 0b0010-0b0001
11111111111111111111111111111110 // ~1 = ~(0b0010-0b0001)
11111111111111111111111111111110 // -2 = ~(0b0010-0b0001)
So you just subtract 0b001 and flip all the bits with the ~ Bitwise operator:
int b = ~(0b0010-0b0001); // ~(2-1) = ~1 = -2
System.out.println(b);
System.out.println(Integer.toBinaryString(b));
Demo

You are confusing storage with presentation. int b has no base, regardless of whether you assign 2, 0b010 or 0x02 to it. Base 10 is just something println assumes.
You can use Integer.toString(number, radix) to print properly signed binary numbers.

Related

How to change the most significant bit to a 1 after shifting an int to the right using '>>'?

For example, when I have a number such as 0x54 in binary that would be 01010100. After using the bit-wise operator '>>' this number will turn into 00101010. Instead of the most significant bit being a 0, I need it to be a one. How can i accomplish this?
Is your number always 8 bits wide? If thats the case you can simply have the decimal representation of 10000000 which is 128 and do a bitwise or
so let's take your example
int val = 84; /// 01010100
int newVal = val >> 1; // 00101010
int mostSig = newVal | 128; // 10101010

Constrained counting sets on binary codes

Problem formulation: Given a binary code of length l, for every t bits set (l%t=0), if there exists at least one bit of value 1, we add 1 to the result.
My question : How to efficiently get the final result?
For example, we have a binary code 010 110 000, and t=3. Then the final result is 2. Since for 000, there is no bit of value 1. For 110, there exists at least one bit of value 1. We add 1 to the result. For 010, there also exists one bit of value 1. We add 1 to the result. Thus, the final result is 2.
My question is that how to efficiently solve this problem without scanning through every t bits, which causes a time complexity linear with the length of the binary code.
For the counting set problem (calculate how many 1's in a binary code), there are some algorithms which take constant time to solve it by taking a limited number of mask and shift operations such as the MIT HAKMEM Count algorithm.
However, existing algorithms for the traditional counting set problem cannot be used to solve my problem.
Does anyone know some tricks for my problems? You can assume a maximum length of the input binary code if it makes the problem easier to solve.
From comment:
Then you can assume that the input is a binary code of 64-bit integer for this problem.
Here are two different ways to do it.
The first run in O(I/t) and works by testing each set for all 0-bits.
public static int countSets(int setSize, long bits) {
Long mask = (1L << setSize) - 1;
int count = 0;
for (long b = bits; b != 0; b >>>= setSize)
if ((b & mask) != 0)
count++;
return count;
}
The second run in O(log I) and works by collapsing the bits of a set to the right-most bit of the set, then counting bits set.
public static int countSets(int setSize, int bitCount, long bits) {
long b = bits, mask = 1;
for (int i = 1; i < setSize; i++)
b |= bits >>> i;
for (int i = setSize; i < bitCount; i <<= 1)
mask |= mask << i;
return Long.bitCount(b & mask);
}
Further explanation
The first method builds a mask for the set, e.g. with t = 3, the mask is 111.
It then shifts the value to the right, t bits at a time, e.g. with input = 010 110 000 and t = 3, you get:
mask = 111
b = 010 110 000 -> b & mask = 000 -> don't count
b = 010 110 -> b & mask = 110 -> count
b = 010 -> b & mask = 010 -> count
result: 2
The second method first merge bits to the right-most bit of the sets, e.g. with input = 010 110 000 and t = 3, you get:
bits = 010 110 000
bits >> 1 = 001 011 000
bits >> 2 = 000 101 100
b (OR'd) = 011 111 100
It then builds a mask for only checking right-most bits, and then applies mask and counts the bits set:
mask = 001 001 001
b & mask = 001 001 000
result: 2

How can I mask a hexadecimal int using Java?

I have an integer that contains a hexa value. I want to extract the first characters from this hexa value like it was a String value but I don't want to convert it to a String.
int a = 0x63C5;
int afterMask= a & 0xFFF;
System.out.println(afterMask); // this gives me "3C5" but I want to get the value "63C"
In my case I can't use String utilities like substring.
It's important to understand that an integer is just a number. There's no difference between:
int x = 0x10;
int x = 16;
Both end up with integers with the same value. The first is written in the source code as hex but it's still representing the same value.
Now, when it comes to masking, it's simplest to think of it in terms of binary, given that the operation will be performed bit-wise. So it sounds like you want bits 4-15 of the original value, but then shifted to be bits 0-11 of the result.
That's most simply expressed as a mask and then a shift:
int afterMask = (a & 0xFFF0) >> 4;
Or a shift then a mask:
int afterMask = (a >> 4) & 0xFFF;
Both will give you a value of (decimal) 1596 = (hex) 63C.
In this particular case, as your input didn't have anything in bits 12+, the mask is unnecessary - but it would be if you wanted an input of (say) 0x1263c5 to still give you an output corresponding to 0x63c.
If you want "63C" all you need is to shift right 4 bits (to drop the right most nibble). Like,
int a = 0x63C5;
int afterMask = a >> 4;
System.out.println(Integer.toHexString(afterMask));
Outputs (as requested)
63c
int a = 0x63C5;
int aftermask = a >> 4 ;
System.out.println( String.format("%X", aftermask) );
The mask you need to use is 0XFFF0

Bitwise op unexpectedly goes negative

Can someone please explain to me why I'm getting these results?
public static int ipv4ToInt(String address) {
int result = 0;
// iterate over each octet
for(String part : address.split(Pattern.quote("."))) {
// shift the previously parsed bits over by 1 byte
result = result << 8;
System.out.printf("shift = %d\n", result);
// set the low order bits to the current octet
result |= Integer.parseInt(part);
System.out.printf("result = %d\n", result);
}
return result;
}
For ipv4ToInt("10.35.41.134"), I get:
shift = 0
result = 10
shift = 2560
result = 2595
shift = 664320
result = 664361
shift = 170076416
result = 170076550
10.35.41.134 = 170076550
This is the same result that I get when I do the math myself.
For ipv4ToInt("192.168.0.1"), I get:
shift = 0
result = 192
shift = 49152
result = 49320
shift = 12625920
result = 12625920
shift = -1062731776
result = -1062731775
192.168.0.1 = -1062731775
For this one, when I do the math manually, I get 3232235521.
Interestingly:
3232235521 = 11000000101010000000000000000001
And when I enter 1062731775 into my Windows calc and hit the +/- button, I get:
-1062731775 = 11111111111111111111111111111111 11000000101010000000000000000001
The function still works for my purposes, but I'm just really curious to know why on earth result is going negative when I do that last bit shift?
Because of bit overflow in your case!
In Java, the integer is also 32 bits and range is from -2,147,483,648 to 2,147,483,647.
12625920 << 8 crosses the limit of 2^31-1 and hence,the result turns negative...
The result just overturns from -ve side and hence,whatever range is left from the positive side is accompanied by that much from negative side!!!
As suggested by everyone,you should use long variable to avoid overflow!
All primitives in java are signed - They can be positive or negative. The highest bit is used to control this, so when it gets set, the number becomes negative.
Try using a long instead - that will give you the wanted result, as longs can be much larger without overflow being hit.
11000000101010000000000000000001 is 32 bits. The value it represents depends on how you interpret those bits:
as a 32bit signed integer, it is negative (because the left-most bit is 1)
as a 32bit unsigned integer, it is positive (like every other unsigned integer)
as the lowers bits of a long (signed or unsigned), it would give a positive value (if the left-most bits stay 0)
Java uses signed integers, so if you print the value, you'll see a negative number. That does not mean your bits are wrong.
It matters only for printing, you can use these ways for printing a positive integer:
1) change result to long (java will do the work for you).
2) handle signed int as unsigned int by yourself (possibly make a method int2string(int n) or toString(int n).
3) Integer.toUnsignedString(int) is you are using java 8.
As far as I understand, your are parsing an IP address, remember, java use signed data types, you can't have a 32 bits integer.
change result to long to fix that.

Casting long to byte in Java

I am unable to understand the following:
In java,
long l = 130L;
byte b = (byte)l;
If I print the value of b, why do I get -126? What is the bit representation of long l?
A byte is a sequence of 8 bits, which makes 2^8 cases = 256. Half of them represent negative numbers, which is -128 to -1. Then there is the 0, and about the half, 1 to 127 represent the positive numbers.
130 as Int looks like 128 + 2 which is:
0000:0000 1000:0000 (128)
0000:0000 0000:0010 (2)
0000:0000 1000:0010 (130)
However, the Byte has just 8 digits, and the assignment takes just the bits as they are, but just the last ones:
1000:0010
The first bit indicates, it is a negative number. Now how much do you need to add to get to zero? Let's do it stepwise:
1000:0010 x +
0000:0001 1 =
----------------
1000:0011 (x+1)
1000:0011 (x+1) +
0000:0001 1 =
----------------
1000:0100 (x+2)
Lets do bigger steps. Just add 1s where we have zeros, but first we go back to x:
1000:0010 x +
0111:1101 y =
--------------
1111:1111
Now there is the turning point: we add another 1, and get zero (plus overflow)
1111:1111 (x + y) +
0000:0001 1
---------
0000:0000 0
If (x+y) + 1 = 0, x+y = -1. A minus 1 is, interestingly, not just the same as 1 (0000:0001) with a 'negative-flag' set ('1000:0001'), but looks completely different. However, the first position always tells you the sign: 1 always indicates negative.
But what did we add before?
0111:1101 y = ?
It doesn't have a 1 at the first position, so it is a positive value. We know how to deconstruct that?
..f:8421 Position of value (1, 2, 4, 8, 16=f, 32, 64 in opposite direction)
0111:1101 y = ?
..f 84 1 = 1+4+8+16+32+64= 125
And now it's clear: x+125 = -1 => x = -126
You may imagine the values, organized in a circle, with the 0 at the top (high noon) and positive values arranged like on a clock from 0 to 5 (but to 127), and the turning point at the bottom (127 + 1 => -128 [sic!].) Now you can go on clockwise, adding 1 leads to -127, -126, -125, ... -3, -2, -1 (at 11 o'clock) and finally 0 at the top again.
For bigger numbers (small, int, long) take bigger clocks, with the zero always on top, the maximum and minimum always on bottom. But even a byte is much too big, to make a picture, so I made one of a nibble, a half-byte:
You can easily fill the holes in the picture, it's trivial!
Btw.: the whole thing isn't called casting. Casting is only used between Objects. If you have something, which is in real a subtype:
Object o = new String ("casting or not?");
this is just an assignment, since a String is (always) an Object. No casting involved.
String s = (String) o;
This is a casting. To the more specific type. Not every object is a String. There is a small relationship to integer promotion, since every byte can be lossless transformed to long, but not every long to byte. However, even Byte and Long, the Object-types, aren't inherited from each other.
You just don't get a warning, for
byte s = (byte) 42;
long o = s; // no problem, no warning
byte b = (byte) o; // written like casting
Bytes are signed in Java - so the range of values is -128 to 127 inclusive.
The bit pattern for 130 as a long, when simply truncated to 8 bits, is the bit pattern for -126 as a byte.
As another example:
int x = 255;
byte b = (byte) x; // b is now -1
You mean byte b = (byte)l?
Java's types are signed, so bytes allow numbers between -128 and +127.
For beginners to understand:
1 byte = 8 bits
Range (derived from 2's complement no. system) = [-2^(n-1) to 2^(n-1)-1], where n is no. of bits
So range is -128 to 127
Whenever value is incremented more than highest possible +ve value, the flow goes to the lowest possible -ve value.
So after value reaches 127 , flow continues from -128 to -127 to -126
to cover a total space of 130 and the thus o/p is -126

Categories