Use java to perform binary shifts [closed] - java

Closed. This question does not meet Stack Overflow guidelines. It is not currently accepting answers.
Questions asking for code must demonstrate a minimal understanding of the problem being solved. Include attempted solutions, why they didn't work, and the expected results. See also: Stack Overflow question checklist
Closed 9 years ago.
Improve this question
I have to take a binary data in java and perform shifts on it.
For e.g. 11110000 when I right shift it by 2 , i.e. 11110000>>00111100
The problem is that, I don't know how to store such a data in Java, as the byte type converts it to decimal format. I need to use the bit at position 6 and XOR it with some other value.
I just need to know how I can achieve the ability to store binary data and perform the required shifts.

If you're using an integer it'll display it in a number format, you can work around it using Integer.toBinaryString(yourByte)
Second, if you're using an integer to store a binary number in the format of 1... (the leftmost bit is 1) then using the operation >> will shift the number right but enter a "new" 1 into the leftmost bit. What you want to do in such case is actually use >>> which prevents that.
If you're using an int to store your byte, and you want to start doing all kind of bit manipulations than you'll have to use a mask, for example, switching between the 3rd and the 5th bits:
int number = 7; //just an example, here binary rep: 00111 => requested output will be 10011
System.out.println("number = " + Integer.toBinaryString(number));
int mask3Bit = 4;//binary rep: 0100
System.out.println("mask3Bit = " + Integer.toBinaryString(mask3Bit));
int mask5Bit = 16; //binary rep: 10000
System.out.println("mask5Bit = " + Integer.toBinaryString(mask5Bit));
// now we'll create a mask that has all the bits on except the 3rd and 5th bit:
int oppositeMask = -1;
oppositeMask ^= mask3Bit;
oppositeMask ^= mask5Bit;
System.out.println("oppositeMask = " + Integer.toBinaryString(oppositeMask));
//check if the 3rd bit is on:
mask3Bit = number & mask3Bit;
//shift twice to the right
mask3Bit <<= 2;
System.out.println("mask3Bit = " + Integer.toBinaryString(mask3Bit));
//now do the same with the 5th bit
//check if the 5th bit is on:
mask5Bit = number & mask5Bit;
//shift twice to the right
mask5Bit >>= 2;
System.out.println("mask5Bit = " + Integer.toBinaryString(mask5Bit));
//now we'll turn off the 3rd and 5th bits in the original number
number &= oppositeMask;
System.out.println("number = " + Integer.toBinaryString(number));
//and use the masks to switch the bits
number |= mask3Bit;
number |= mask5Bit;
//let's check it out now:
System.out.println("new number = " + Integer.toBinaryString(number));
OUTPUT:
number = 111
mask3Bit = 100
mask5Bit = 10000
oppositeMask = 11111111111111111111111111101011
mask3Bit = 10000
mask5Bit = 0 //here it's zero cause the original number has zero in the 5th bit and we used &. If the bit was on we would have gotten '100'
number = 11
new number = 10011

Related

Understanding Pointer Arithmetic of Array Declared in C [closed]

Closed. This question needs to be more focused. It is not currently accepting answers.
Want to improve this question? Update the question so it focuses on one problem only by editing this post.
Closed 2 years ago.
Improve this question
I am trying to convert some C code into another language (eg: Java or C#). The problem is understanding a few things about how these arrays are being declared and used...
This is the minimum code that demonstrates my issue:
static void some_function ( )
{
int16_t arr_tmpShort[120 + 40], *ptr0, *ptr1;
int offset = 5;
//assume that "arr_tmpShort" is now filled with some values
ptr0 = arr_tmpShort + 84 - offset;
ptr1 = arr_tmpShort + 85;
}
So I need a second opinion:
This line:
int16_t arr_tmpShort[120 + 40];
is creating an array for holding 160 entries of Shorts. That plus sign is doing nothing special except simple arithmetic, right?
Problem: Now these lines
ptr0 = arr_tmpShort + 84 - offset;
ptr1 = arr_tmpShort + 85;
are strange cos I'm seeing arithmetic on an array.
This is new to me and after some research I need clarification on which of the below is more valid or true...
ptr0 = arr_tmpShort + 84 is equal to Java/C# as arr_tmpShort[84] (a position in array)?
Is it considered as ptr0 =
either (arr_tmpShort[84] - offset); //get [84] Short value and minus it by offset?
or (arr_tmpShort[84 - offset]); //get [84 - offset] Short value from array?
1) Yes, most likely that will be optimized out to 160 by the compiler.
2) In c, you can think of arrays and pointers as being the same thing.
So, when you have code like i[3] this would be equivalent to writing *(i+3). Both of these return the value of the element stored in the 3rd memory location after the start of the array i. More information on pointers can be found here
So ptr0 = arr_tmpShort + 84 - offset is going to be equal to the memory location of arr_tmpShort[84 - offset] which in this case is arr_tmpShort[79].
Later you could also write *ptr0 and if no other modifications are made, it would be equal to arr_tmpShort[79].
C pointer arithmetic: https://www.tutorialspoint.com/cprogramming/c_pointer_arithmetic.htm
ptr0 = arr_tmpShort + 84 is equal to Java/C# as arr_tmpShort[84] (a position in array)?
No. It calculates the address needed, but doesn't actually access a value (either read or write).
Is it considered as ptr0 =
or (arr_tmpShort[84 - offset]); //get [84 - offset] Short value from array?
It's closest to this one, but again there's no access of the element. The address of arr_tmpShort[84-offset] is caculated, but no access is done yet.
To access the element, you typically have to derefernce the variable.
ptr0 = arr_tmpShort + 84;
short x = *ptr0; // this retrieves the 84th element, assuming a short

Convert 32bit data to unsigned long value

I have something like this:
int[0] = 4123;
int[1] = 2571;
I would like to combine them and make one long value in Java.
This is my attempt:
int[] r = { 4123, 2571 };
long result = ( (r[1] & 0xFFFF) << 16 | (rs[0] & 0xFFFF) );
System.out.prinln(result);
The output should be: 10111627 but I get 168497179. Probably I miss something in conversion but don't have idea what...
EDIT
This is example how the value is placed into 32-bit register.
I try the summarize and hopefully clarify what the several comments on your question already indicate:
If you want to get the number from your image which is
00001010 00001011 00010000 00011011 = 0x0A0B101B = 168497179
in one single long value and you have two ints
0001000000011011 = 0x101B = 4123 and
0000101000001011 = 0x0A0B = 2571
than your code is correct.
I would recommend you to get used to hexadecimal numbers as they show easily that there is no binary relation between 0x0A0B & 0x101B and 0x009A4A8B = 10111627.
BTW your image is contradictory: the binary numbers represent as seen above the number 0x0A0B101B but the hexadecimals read 0x0A0B101E (notice the E) while the decimals support the binary value.
Finally, I figured out your flaw:
You seem to expect to get the decimal number concatenated together as result. But unlike the hexadecimals here it does not work this way in decimal!
Let me elaborate that. You have the binary number:
00001010 00001011 00010000 00011011
Which you can easily convert to hex block by block
0x0A 0x0B 0x10 0x1B
and than just join them together
0x0A0B101B
But that magic join is just a simplification only applying to hex (and the reason why hex is so popular among programmers).
The long version is you have to multiply the higher blocks/bytes (towards the left) with the 'basis' of the preceding block (to the right). The right most block is always multiplied by 1. The base for the next block is (since there are 8 bits in the first block) 28 = 256 = 0x100. The base for the third block is (8+8 bits) 216 = 65536 = 0x10000. The last (left most) has to be multiplied by (8+8+8 bits) 224 = 16777216 = 0x1000000.
Lets make an example for the first two blocks:
Hexadecimal:
0x10 || 0x1B
(0x10 * 0x100) + (0x1B* 0x1)
0x1000 + 0x1B = 0x101B
Decimal:
16 || 27
(16 * 256) + (27 * 1)
4096 + 27 = 4123
As you can see on your image they both in it (notice the E/B issue which is in decimal a 6/3 issue) but there is no 1627. So converting binary or hexadecimal numbers to decimal is a nontrivial task (for humans), best to use a calculator.

String to binary?

I have a very odd situation,
I'm writing a filter engine for another program, and that program has what are called "save areas". Each of those save areas is numbered 0 through 32 (why there are 33 of them, I don't know). They are turned on or off via a binary string,
1 = save area 0 on
10 = save area 1 on, save area 0 off
100 = save area 2 on, save areas 1 and 0 off.
and so on.
I have another program passing in what save areas it needs, but it does so with decimal representations and underscores - 1_2_3 for save areas 1, 2, and 3 for instance.
I would need to convert that example to 1110.
What I came up with is that I can build a string as follows:
I break it up (using split) into savePart[i]. I then iterate through savePart[i] and build strings:
String saveString = padRight("0b1",Integer.parseInt(savePart[i]));
That'll give me a string that reads "0b1000000" in the case of save area 6, for instance.
Is there a way to read that string as if it was a binary number instead. Because if I were to say:
long saveBinary = 0b1000000L
that would totally work.
or, is there a smarter way to be doing this?
long saveBinary = Long.parseLong(saveString, 2);
Note that you'll have to leave off the 0b prefix.
This will do it:
String input = "1_2_3";
long areaBits = 0;
for (String numTxt : input.split("_")) {
areaBits |= 1L << Integer.parseInt(numTxt);
}
System.out.printf("\"%s\" -> %d (decimal) = %<x (hex) = %s (binary)%n",
input, areaBits, Long.toBinaryString(areaBits));
Output:
"1_2_3" -> 14 (decimal) = e (hex) = 1110 (binary)
Just take each number in the string and treat it as an exponent. Accumulate the total for each exponent found and you will get your answer w/o the need to remove prefixes or suffixes.
// will contain our answer
long answer = 0;
String[] buckets = givenData.split("_"); // array of each bucket wanted, exponents
for (int x = 0; x < buckets.length; x++){ // iterate through all exponents found
long tmpLong = Long.parseLong(buckets[x]); // get the exponent
answer = (10^tmpLong) + answer; // add 10^exponent to our running total
}
answer will now contain our answer in the format 1011010101 (what have you).
In your example, the given data was 1_2_3. The array will contain {"1", "2", "3"}
We iterate through that array...
10^1 + 10^2 + 10^3 = 10 + 100 + 1000 = 1110
I believe this is also why your numbers are 0 - 32. x^0 = 1, so you can dump into the 0 bucket when 0 is in the input.

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.

check number present in a sequences

I am writing a program which I found on a coding competition website, I have sort of figured out how to solve the problem but, I am stuck on a math part of it, I am completely diluting the problem and showing what I need.
first I need to check if a number is part of a sequence, my sequence is 2*a+1 where a is the previous element in the sequence or 2^n-1 to get nth item in the sequence. so it is 1,3,7,15,31,63...
I don't really want to create the whole sequence and check if a number is present, but I am not sure what a quicker method to do this would be.
Second if I am given a number lets say 25, I want to figure out the next highest number in my sequence to this number. So for 25 it would be 31 and for 47 it would be 63, for 8 it would be 13.
How can i do these things without creating the whole sequence.
I have seen similar questions here with different sequences but I am still not sure how to solve this
Start by finding the explicit formula for any term in your sequence. I'm too lazy to write out a proof, so just add 1 to each term in your sequence:
1 + 1 = 2
3 + 1 = 4
7 + 1 = 8
15 + 1 = 16
31 + 1 = 32
63 + 1 = 64
...
You can clearly see that a_n = 2^n - 1.
To check if a particular number is in your sequence, assume that it is:
x = 2^n - 1
x + 1 = 2^n
From Wikipedia:
The binary representation of integers makes it possible to apply a
very fast test to determine whether a given positive integer x is a
power of two:
positive x is a power of two ⇔ (x & (x − 1)) equals to zero.
So to check, just do:
bool in_sequence(int n) {
return ((n + 1) & n) == 0;
}
As #Blender already pointed out your sequence is essentially 2^n - 1, you can use this trick if you use integer format to store it:
boolean inSequence(int value) {
for (int i = 0x7FFF; i != 0; i >>>= 1) {
if (value == i) {
return true;
}
}
return false;
}
Note that for every elements in your sequence, its binary representation will be lots of 0s and then lots of 1s.
For example, 7 in binary is 0000000000000000000000000000111 and 63 in binary is 0000000000000000000000000111111.
This solution starts from 01111111111111111111111111111111 and use an unsigned bitshift, then compare if it is equal to your value.
Nice and simple.
How to find the next higher number :
For example, we get 19 ( 10011 ) , should return 31 (11111)
int findNext(int n){
if(n == 0) return 1;
int ret = 2; // start from 10
while( (n>>1) > 0){ // end with 100000
ret<<1;
}
return ret-1;
}

Categories