convert four 32 bits ints to IP address in java - java

Using the code found here: https://libbits.wordpress.com/2011/05/17/check-if-ip-is-within-range-specified-in-cidr-in-java/
// Step 1. Convert IPs into ints (32 bits).
// E.g. 157.166.224.26 becomes 10011101 10100110 11100000 00011010
int addr = (( 157 << 24 ) & 0xFF000000)
| (( 166 << 16 ) & 0xFF0000)
| (( 224 << 8 ) & 0xFF00)
| ( 26 & 0xFF);
// Step 2. Get CIDR mask
int mask = (-1) << (32 - 10);
// Step 3. Find lowest IP address
int lowest = addr & mask;
// Step 4. Find highest IP address
int highest = lowest + (~mask);
I'm able to split a string into four ints and create boundaries for my IP range.
Now I want to be able to generate an ip that is between the highest and lowest values. For example:
given the range: 157.166.224.26/10 I get an address of -1650008038 my lowest ip address is -1652555776 and highest ip address is -1648361473. Now I need to generate a number that is between my lowest and highest and convert it back to four integers, this last part is where I'm lost at, I'm not sure how to convert -1648361473 to an ip address

That's pretty easy. Let say the IPv4 address is in the ipaddr variable, you can write something like that:
byte[] addr = new byte[4];
addr[0] = (ipaddr >> 24) & 0xFF;
addr[1] = (ipaddr >> 16) & 0xFF;
addr[2] = (ipaddr >> 8 ) & 0xFF;
addr[3] = ipaddr & 0xFF;
InetAddress inetAddr = InetAddress.getByAddress(addr);

The answer that Teetoo made above deserves some explanation.
Lets start with the first value:
(ipaddr >> 24) & 0xFF
When this is shifted down, the 8 bits representing the 157 are in the rightmost position of the resulting integer. However, since the value was initially negative, you would have 1's in 24 most significant bits, which would end up giving you a negative number. What you want is to 0 out all but those last 8 bits, hence the "& 0xFF". Another way to do this would be to right shift using the >>> operator which forces 0's into the most significant bits.
(ipaddr >>> 24)
now we move on to:
(ipaddr >> 16) & 0xFF
When you shift, you'll have the 16 leftmost bits set to 1 (due to shifting a negative number). Then you'll have the 8 bits representing the 157 and then the 8 bits representing 166. In this case, the >>> operator wouldn't help us because we still have the 157 in there. So the "& 0xFF" will 0 out all but the 8 bits for the 166.
Similarly for the last two values.

an addition to #Teetoo's answer.
let's ByteBuffer do the int to byte array magic
ByteBuffer bb = ByteBuffer.wrap (addr);
bb.putInt (iIP);

You can use
int addr = (157 << 24) | (166 << 16) | (224 << 8) | 26;
to reverse this.
byte[] addrAsBytes = { (byte) (addr >> 24), (byte) (addr >> 16),
(byte) (addr >> 8), (byte) addr };

Related

How to convert one byte and 4 bits from another byte to a short using bitwise?

Using bitwise, how could we convert these 3 bytes to two shorts in this pattern in the most performant way?:
(11111111)(01111110)(10000001) 3 bytes
(111111110111)(111010000001) 2 shorts
Found a way to combine two bytes into a short, but for a combination of 1 byte and 4 bits tried a variety of ways for hours with no success. Thanks for your help.
byte byt1 = -1; // 11111111
byte byt2 = 126;// 01111110
byte byt3 = 129;// 10000001
short s_1_2 = (short) ((byt1 << 8) | (byt2 & 0xFF));
// value is 1111111101111110
short s1 = // want to be 111111110111
short s2 = // want to be 111010000001
One of the possibilities is the following:
short s1 = (short) (((byt1 & 0xff) << 4) | ((byt2 & 0xf0) >> 4));
short s2 = (short) (((byt2 & 0x0f) << 8) | (byt3 & 0xff));

Android 8 bit to 16 bit representation for Negative Numbers

Refer to the question How to Convert two 8 bit represented byte to single 16 bit represented integer value in Android.
I got an answer like this
short yourinteger16 = (short)(((bytes[0] & 0xFF) << 8) | (bytes[1] & 0xFF));
This answer is correct for the positive number. But in the case of the negative number, it's failing.
For example, I am sending the value from the BLE to the application as -10. The value will convert from the BLE as -10000 because of mAh/mV conversion of current and voltage. These values are split into two bytes and I am getting the byte value as -39 and -16 in my application. I am passing the byte to the method as like below.
short yourinteger16 = (short)(((-39 & 0xFF) << 8) | (-16 & 0xFF));
But I am getting the result as 9.77 as the float value of yourinteger16 .
Anyone has any idea about this?. Any solution please update me.
Full Code:
Integer ampValue = null;
if (mBleDataHashMap.containsKey(SuperMuttBleConst.RESP_I_HIGH) &&
mBleDataHashMap.containsKey(SuperMuttBleConst.RESP_I_LOW)) {
ampValue = get8ByteTo16Byte(mBleDataHashMap.get(SuperMuttBleConst.RESP_I_HIGH),
mBleDataHashMap.get(SuperMuttBleConst.RESP_I_LOW));
}
if (ampValue != null) {
float newAmp = ampValue.floatValue();
newAmp = newAmp/1000;
mAmpTextvw.setText("" + newAmp);
}
Method
protected Integer get8ByteTo16Byte(int firstValue, int secondValue) {
Short integerValue = (short)((((byte) firstValue & 0xFF) << 8) | ((byte) secondValue & 0xFF));
return new Integer(integerValue);
}
You're receiving -39 and -16 perfectly (the high and low bytes for -10000, respectively).
Use addition instead of ORing the high and low bytes.
Please try the following
short result = (short) (((short)(-39 & (byte)0xFF) << 8) + (short)(-16 & (byte)0xFF));
The negative low bytes is causing trouble for the high byte when dealing with 2's complement arithmetic.

Bit shifting for >32 bit long

I am trying to extract the first 49 bits from a 7 byte array. I approached this byte using masks and bit shifting as follows:
long byteVal = ((decryptedVCW[6] & 0xff)&((decryptedVCW[6] & 0xff)<<7)) | ((decryptedVCW[5] & 0xff) << 8) | ((decryptedVCW[4] & 0xff) << 16) | ((decryptedVCW[3] & 0xff) << 24) | ((decryptedVCW[2] & 0xff) << 32) | ((decryptedVCW[1] & 0xff) << 40) | ((decryptedVCW[0] & 0xff) << 48);
Where decryptedVCW is a 56 bit byte array.
The masking and bit shifting work as expected until the 32 bit shift '<<32'.
As an example, the hex for decryptedVCW is E865037A9C6424 of which in binary is:
11101000011001010000001101111010100111000110010000100100
When I perform the above shifting I get 7AFC6503 in binary:
1111010111111000110010100000011
Does anyone have any idea why the bit shifting falls apart at 32 upwards and how to go about solving this issue?
Many thanks
Shiv
The type of decryptedVCW[2] & 0xff is int, since the first operand is byte and the second is an int literal.
When the first operand of the << operator is int, you are shifting an int, so if the second operand is 32, you'll get int overflow.
You can cast the first operand of the << operator to long :
(((long)(decryptedVCW[2] & 0xff)) << 32)
or you can force the first operand to be a long by using a long literal in the & operation, as suggested by #shmosel :
(decryptedVCW[2] & 0xFFL) << 32

use of the bitwise operators to pack multiple values in one int

Low level bit manipulation has never been my strong point. I will appreciate some help in understanding the following use case of bitwise operators.Consider...
int age, gender, height, packed_info;
. . . // Assign values
// Pack as AAAAAAA G HHHHHHH using shifts and "or"
packed_info = (age << 8) | (gender << 7) | height;
// Unpack with shifts and masking using "and"
height = packed_info & 0x7F; // This constant is binary ...01111111
gender = (packed_info >> 7) & 1;
age = (packed_info >> 8);
I am not sure what this code is accomplishing and how? Why use the magic number 0x7F ? How is the packing and unpacking accomplished?
Source
As the comment says, we're going to pack the age, gender and height into 15 bits, of the format:
AAAAAAAGHHHHHHH
Let's start with this part:
(age << 8)
To start with, age has this format:
age = 00000000AAAAAAA
where each A can be 0 or 1.
<< 8 moves the bits 8 places to the left, and fills in the gaps with zeroes. So you get:
(age << 8) = AAAAAAA00000000
Similarly:
gender = 00000000000000G
(gender << 7) = 0000000G0000000
height = 00000000HHHHHHH
Now we want to combine these into one variable. The | operator works by looking at each bit, and returning 1 if the bit is 1 in either of the inputs. So:
0011 | 0101 = 0111
If a bit is 0 in one input, then you get the bit from the other input. Looking at (age << 8), (gender << 7) and height, you'll see that, if a bit is 1 for one of these, it's 0 for the others. So:
packed_info = (age << 8) | (gender << 7) | height = AAAAAAAGHHHHHHH
Now we want to unpack the bits. Let's start with the height. We want to get the last 7 bits, and ignore the first 8. To do this, we use the & operator, which returns 1 only if both of the input bits are 1. So:
0011 & 0101 = 0001
So:
packed_info = AAAAAAAGHHHHHHH
0x7F = 000000001111111
(packed_info & 0x7F) = 00000000HHHHHHH = height
To get the age, we can just push everything 8 places to the right, and we're left with 0000000AAAAAAAA. So age = (packed_info >> 8).
Finally, to get the gender, we push everything 7 places to the right to get rid of the height. We then only care about the last bit:
packed_info = AAAAAAAGHHHHHHH
(packed_info >> 7) = 0000000AAAAAAAG
1 = 000000000000001
(packed_info >> 7) & 1 = 00000000000000G
This could be a rather long lesson in bit manipulation but first let me point you too the bit masking article on Wikipedia.
packed_info = (age << 8) | (gender << 7) | height;
Take age and move it's value over 8 bits then take gender and move it over 7 bits and height will occupy the last bits.
age = 0b101
gender = 0b1
height = 0b1100
packed_info = 0b10100000000
| 0b00010000000
| 0b00000001100
/* which is */
packed_info = 0b10110001100
Unpacking does the reverse but uses masks like 0x7F (which is 0b 01111111) to trim out the other values in the field.
gender = (packed_info >> 7) & 1;
Would work like...
gender = 0b1011 /* shifted 7 here but still has age on the other side */
& 0b0001
/* which is */
gender = 0b1
Note that ANDing anything to 1 is the same as "keeping" that bit and ANDing with 0 is the same as "ignoring" that bit.
If you were going to store a date as a number, maybe you would accomplish it by multiplying the year by 10000, the month by 100 and adding the day. A date such as July, 2, 2011 would be encoded as the number 20110702:
year * 10000 + month * 100 + day -> yyyymmdd
2011 * 10000 + 7 * 100 + 2 -> 20110702
We can say that we encoded the date in a yyyymmdd mask. We could describe this operation as
Shift the year 4 positions to the left,
shift the month 2 positions to the left and
leave the day as is.
Then combine the three values together.
This is the same thing that is happenning with the age, gender and height encoding, only that the author is thinking in binary.
See the ranges that those values may have:
age: 0 to 127 years
gender: M or F
height: 0 to 127 inches
If we translate those values to binary, we would have this:
age: 0 to 1111111b (7 binary digits, or bits)
gender: 0 or 1 (1 bit)
height: 0 to 1111111b (7 bits also)
With this in mind, we can encode the age-gender-height data with the mask aaaaaaaghhhhhhh, only that here we are talking about binary digits, not decimal digits.
So,
Shift the age 8 bits to the left,
shift the gender 7 bits to the left and
leave the height as is.
Then combine all three values together.
In binary, the Shift-Left operator (<<) moves a value n positions to the left. The "Or" operator ("|" in many languages) combines values together. Therefore:
(age << 8) | (gender << 7) | height
Now, how to "decode" those values?
It's easier in binary than in decimal:
You "mask away" the height,
shift the gender 7 bits to the right and mask that away also, and finally
shift the age 8 bits to the right.
The Shift-Right operator (>>) moves a value n positions to the right (whatever digits shifted "out" of the rightmost position are lost). The "And" binary operator ("&" in many languages) masks bits. To do that it needs a mask, indicating which bits to preserve and which bits to destroy (1 bits are preserved). Therefore:
height = value & 1111111b (preserve the 7 rightmost bits)
gender = (value >> 1) & 1 (preserve just one bit)
age = (value >> 8)
Since 1111111b in hex is 0x7f in most languages, that's the reason for that magic number. You would have the same effect by using 127 (which is 1111111b in decimal).
Same requirement I have faced many times. It is very easy with the help of Bitwise AND operator. Just qualify your values with increasing powers of two(2). To store multiple values, ADD their relative number ( power of 2 ) and get the SUM. This SUM will consolidate your selected values. HOW ?
Just do Bitwise AND with every value and it will give zero (0) for values which were not selected and non-zero for which are selected.
Here is the explanation:
1) Values ( YES, NO, MAYBE )
2) Assignment to power of two(2)
YES = 2^0 = 1 = 00000001
NO = 2^1 = 2 = 00000010
MAYBE = 2^2 = 4 = 00000100
3) I choose YES and MAYBE hence SUM:
SUM = 1 + 4 = 5
SUM = 00000001 + 00000100 = 00000101
This value will store both YES as well as MAYBE. HOW?
1 & 5 = 1 ( non zero )
2 & 5 = 0 ( zero )
4 & 5 = 4 ( non zero )
Hence SUM consists of
1 = 2^0 = YES
4 = 2^2 = MAYBE.
For more detailed explanation and implementation visit my blog
A more condense answer:
AAAAAAA G HHHHHHH
Packing:
packed = age << 8 | gender << 7 | height
Alternatively you can just sum components if ie when used in MySQL SUM aggregate function
packed = age << 8 + gender << 7 + height
Unpacking:
age = packed >> 8 // no mask required
gender = packed >> 7 & ((1 << 1) - 1) // applying mask (for gender it is just 1)
height = packed & ((1 << 7) - 1) // applying mask
Another (longer) example:
Say you have an IP address you want to pack, however it is a fictional IP address eg
132.513.151.319. Note that some components greater then 256 which requires more then 8 bits unlike real ip addresses.
First we need to figure out what offset we need to use to be able to store the max number.
Lets say with our fictional IPs no component can be bigger then 999 that means we need 10 bits of storage per component (allows numbers up to 1014).
packed = (comp1 << 0 * 10) | (comp1 << 1 * 10) | (comp1 << 2 * 10) | (comp1 << 3 * 10)
Which gives dec 342682502276 or bin 100111111001001011110000000010010000100
Now lets unpack the value
comp1 = (packed >> 0 * 10) & ((1 << 10) - 1) // 132
comp2 = (packed >> 1 * 10) & ((1 << 10) - 1) // 513
comp3 = (packed >> 2 * 10) & ((1 << 10) - 1) // 151
comp4 = (packed >> 3 * 10) & ((1 << 10) - 1) // 319
Where (1 << 10) - 1 is a binary mask we use to hide bits on the left beyond the 10 right most bits we are interested in.
Same example using MySQL query
SELECT
(#offset := 10) AS `No of bits required for each component`,
(#packed := (132 << 0 * #offset) |
(513 << 1 * #offset) |
(151 << 2 * #offset) |
(319 << 3 * #offset)) AS `Packed value (132.513.151.319)`,
BIN(#packed) AS `Packed value (bin)`,
(#packed >> 0 * #offset) & ((1 << #offset) - 1) `Component 1`,
(#packed >> 1 * #offset) & ((1 << #offset) - 1) `Component 2`,
(#packed >> 2 * #offset) & ((1 << #offset) - 1) `Component 3`,
(#packed >> 3 * #offset) & ((1 << #offset) - 1) `Component 4`;
The left shift operator means "multiply by two, this many times". In binary, multiplying a number by two is the same as adding a zero to the right side.
The right shift operator is the reverse of the left shift operator.
The pipe operator is "or", meaning overlay two binary numbers on top of each other, and where there is a 1 in either number the result in that column is a 1.
So, let's extract the operation for packed_info:
// Create age, shifted left 8 times:
// AAAAAAA00000000
age_shifted = age << 8;
// Create gender, shifted left 7 times:
// 0000000G0000000
gender_shifted = gender << 7;
// "Or" them all together:
// AAAAAAA00000000
// 0000000G0000000
// 00000000HHHHHHH
// ---------------
// AAAAAAAGHHHHHHH
packed_info = age_shifted | gender_shifted | height;
And the unpacking is the reverse.
// Grab the lowest 7 bits:
// AAAAAAAGHHHHHHH &
// 000000001111111 =
// 00000000HHHHHHH
height = packed_info & 0x7F;
// right shift the 'height' bits into the bit bucket, and grab the lowest 1 bit:
// AAAAAAAGHHHHHHH
// >> 7
// 0000000AAAAAAAG &
// 000000000000001 =
// 00000000000000G
gender = (packed_info >> 7) & 1;
// right shift the 'height' and 'gender' bits into the bit bucket, and grab the result:
// AAAAAAAGHHHHHHH
// >> 8
// 00000000AAAAAAA
age = (packed_info >> 8);
You can see the expression x & mask as an operation that removes from x the bits that are not present (i.e., have value 0) in mask. That means, packed_info & 0x7F removes from packed_info all the bits that are above the seventh bit.
Example: if packed_info is 1110010100101010 in binary, then packed_info & 0x7f will be
1110010100101010
0000000001111111
----------------
0000000000101010
So, in height we get the lower 7 bits of packed_info.
Next, we are shifting the whole packed_info by 7, this way we remove the information which we have already read out. So we get (for the value from previous example) 111001010 The gender is stored at the next bit, so with the same trick: & 1 we are extracting only that bit from the information. The rest of the information is contained at offset 8.
Packing back is not complicated, too: you take age, shift it 8 bits (so you get 1110010100000000 from 11100101), shift the gender by 7 (so you get 00000000), and take the height (assuming it would fit lower 7 bits). Then, you are composing all of them together:
1110010100000000
0000000000000000
0000000000101010
----------------
1110010100101010

Binary representation in Java

I am finding it difficult to understand and work with this binary representation in java:
With the help of the user Jon Skeet, I understood that binary representation should be built this way.
Here's a code sample:
public class chack {
public static void main(String[] args) {
int num2=2;
int num3=3;
int num4=4;
int num1=1;
int nirbinary = (num1 << 24) | (num2 << 16) | (num3 << 8) | num4;
System.out.println(nirbinary);
String nir= Integer.toBinaryString(nirbinary);
System.out.println(nir);
}
}
Couple of question:
How does one get num1 (for example) back from an int who is already in this binary
why do I get 16909060 when I print nirbinary- what does it stands for?
How does one get num1 (for example) back from an int who is already in this binary
representation?
Thank you
I am not completely sure what you are missing, so I will just explain how you can convert integers to binary strings back and forth in java.
You can get a binary string from an integer like so:
int i = 1234;
String binString = Integer.toBinaryString(i);
and you can convert the string back to an integer this way:
int iNew = Integer.parseInt(binString, 2);
Note the second argument to Integer.parseInt() is the desired base of the number. 2 is binary, 8 is octal, 10 decimal, etc.
16909060 stands for the number 16909060.
It is (1 * 224) + (2 * 216) + (3 * 28) + 4.
To get num1 back out, just right-shift the result the same amount you left-shifted and mask out the other bytes (not always necessary for num1(*), but for the others):
int num1 = nirbinary >> 24 & 0xFF;
int num2 = nirbinary >> 16 & 0xFF;
int num3 = nirbinary >> 8 & 0xFF;
int num4 = nirbinary & 0xFF;
Note that nirbinary is not "a binary representation". Or more precisely: it's no more or less binary than num1, num2, num3 and num4: internally all numbers (and characters, and booleans, ...) are stored in binary.
(*) note that if num1 is > 127, then you either need to use >>> to do the right-shift or use the & 0xFF in order to ensure that the correct value is restored. The difference between >> and >>> are the "new" bits inserted on the "left" side of the value: With >> they will depend on the highest-value bit (known as sign-extension) and with >>> they will always be 0.
Every int is a number, it's not binary, hex or decimal, it's just a number. the statement (num1 << 24) | (num2 << 16) | (num3 << 8) | num4; is a binary manipulation of 4 ints into another int. It doesn't change the representation of nirbinary to binary, since nirbinary has no representation, because (again) it's just a number.
Integer.toBinaryString(nirbinary) returns the binary representation of nirbinary which means "how would nibinary look like in base-2".
If you have a String which is a binary representation of a number, you could get its value, by using Integer.parseint(yourbinaryrepresentation, yourbase); for example - Integer.parseint(nir, 2);
And another thing:
You can't always get back one of the numbers back from nirbinary, since you performed a bit manipulation that is not reversible, for example:
int i1 = 5; //binary 0101
int i2 = 4; //binary 0100
int i3 = i1 | i2; //binary 0101
you cannot recognize each of your variables (i1, i2) since they have a common bit, i3 could have been the result of or on two other numbers:
int i1 = 1; //binary 0101
int i2 = 4; //binary 0100
int i3 = i1 | i2; //binary 0101
in your case, if each number is smaller than 256, you can reverse it with the following operation:
int myoldnumber = (nirbinary >> previousShift) & 0xff;
for example, to retrieve num1 you can do:
int retrievedNum1 = (nirbinary >> 24) & 0xff;
Here no need to depend only on binary or any other format...
one flexible built in function is available
That prints whichever format you want in your program..
Integer.toString(int,representation);
Integer.toString(100,8) // prints 144 --octal representation
Integer.toString(100,2) // prints 1100100 --binary representation
Integer.toString(100,16) //prints 64 --Hex representation
Integer.toString(100,5) // prints 400 --Base 5
When working with bitshifting and integers I would recommend you think in hexadecimal numbers, that will usually make life a lot easier. Just keep in mind that 8 bits represent 1 byte and 1 byte covers the hex-range from 0x00 to 0xFF
Since num1 to num4 are smaller than 10, their decimal representation is equal to their hex representiation, ie 1 = 0x01, 2 = 0x02 etc..
As I told you: 1 Byte is 8 bits. In your bitshifting operation you always shift multiple of 8.
So 0x01 << 8 => 0x0100
0x01 << 16 => 0x010000
etc.
So you basically only add zero bytes, which of course increases the value.
What you do next is to | them, a bitwise or. This means that two bitfields get modified in such a way that the result has a 1 at one place if at least one of the input values as a 1 there. Since your shifted ints contain only zero at the back, a bitwise or is nothing else then to put the value in this spot.
E.g:
(0x01 << 8) | 0x02
0x01 << 8 will produce 0x0100. Now you simply have to replace the last 00 with 02, since you or them: 0x0102
If you want to recreate the original int, you have to mask the part that int represents (this is easy since the parts do not overlap in your example) and then shift it back.
E.g.
Say ou produced 0x010203 and want to have only 0x02. You now have to mask shift it back 0x010203 >> 8 which will put the 02 in the last part. Now simply mask this last part 0x0102 && 0xFF. This will set all but the last 8 bits to zero
it's basically 1 * 2^24 + 2 * 2^16 + 3 * 2^8 + 4 = 16909060
You can get num1 by doing num1 = nirbinary >> 24.
What did you expect instead?
To get the most significant byte from an int i:
(i >> 24) & 0xff

Categories