I am trying to figure out why if I shift the negative integer -1 I always get -1, e.g.:
echo -1 >> 64; // -1
echo -1 >> 5; // -1
echo -1 >> 43; // -1
echo -1 >> 1; // -1
Whatever second operand of the right shift is given, -1 remains -1... I do understand that when you perform a right shift you're actually doing this:
x >> y = x / 2^y
But in the case of x being -1, if so, I do:
-1 >> 3 = -1 / 2^3
Shouldn't this value be -1/8 = -0.125?
Thanks for the attention.
Bitwise shift operators don't divide. They do what they are supposed to do - shift bits. In particular, the right shift operator does the following:
for each bit starting from the right, set its value to what's on the left of it
for the leftmost bit, which has nothing on the left, keep its current value
For example, if your number is
1011...101
right shift gives you
11011...10
So the rightmost bit (LSB) is lost and the leftmost bit (MSB) is duplicated. This is called "sign propagation", because MSB is used to distinguish positive (MSB=0) from negative (MSB=1) numbers.
Negative numbers are stored as "two's complement", that is, on a 32-bit system, -x is stored as 2^32-x. So, -1 is 10...00 (32 zeroes) - 1 == 1...1 (32 ones). If you shift 32 ones according to the above procedure, you get 32 ones yet again, that is, -1 >> whatever will always be -1.
The difference between the right shift and division by two is that the shift gives same results for odd and even numbers. Since the rightmost bit is lost, when you shift an odd number (which has LSB=1), the result is the same as shifting the next lower even number (the same combination of bits, but with LSB=0). So, you get no halves when you shift, since the dividend is forced to be even. For example,
1010 = 10102, 10 / 2 = 5.0 and 10 >> 1 == 510 == 1012
1110 = 10112, 11 / 2 = 5.5 but 11 >> 1 == 510 == 1012
If you prefer to think about x >> 1 in terms of division, it first "rounds" x down to an even number (x - abs(x) % 2) and then divides that number by two.
For x = -1 this gives you (-1 - abs(-1) % 2)/2 == (-1 - 1)/2 = -2/2 = -1.
It is the same in all languages I know - bitwise arithmetic right shift for -1 will be -1, and as others mentioned, this operation can be applied only to integers.
-1 is represented in binary as all bits filled with value 1. For arithmetic right shift the bits will be shifted to the right, and the highest bit (at the left) will be filled with sign of the value, for negative values it will be 1, and for positive - 0. So it makes -1 again after the shift.
There are other kinds of bitwise shifts, and for logical right shift the highest bit would be filled with zero. You can get some more info here: http://en.wikipedia.org/wiki/Bitwise_operation#Arithmetic_shift
Related
I have the necessity to store many numbers (i can decide which numbers) as a single unique number from which i should be able to retrieve the original number.
I already know 2 ways to do this:
1) Fundamental theorem of arithmetic (Prime Numbers)
Say i have 5 values, i assign a prime number other than 1 to each value
a = 2
b = 3
c = 5
d = 7
e = 13
If i want to store a, b and c i can multiply them 2*3*5=30 and i know no other product of primes can be 30. Then to check if a value contains, for example, b, all i need to do is 30 % b == 0
2) Bitmask
Just like Linux permissions, use powers of 2 and sum each value
But these 2 methods grow up fast (1st way faster than 2nd), and using prime numbers requires me to have a lot of primes.
Is there any other method to do this efficiently when you have, for example, a thousand values?
If you are storing, say, base 10 numbers, then do a conversion through base 11 numbers. With the increased base, you have an extra 'digit'. Use that digit as a separator. So, three base 10 numbers "10, 42, 457" become "10A42A457": a single base 11 number (with 'A' as the additional digit).
Whatever base your original numbers are in, increase the base by 1 and concatenate, using the extra digit as a separator. That will give you a single number in the increased base.
That single number can be stored in whatever number base you find convenient: binary, denary or hex for example.
To retrieve your original numbers just convert to base 11 (or whatever) and replace the extra digit with separators.
ETA: You don't have to use base 11. The single number "10A42A457" is also a valid hexadecimal number, so any base of 11 or above could be used. Hex may be easier to work with than base 11.
Is there any other method to do this efficiently when you have, for example, a thousand values?
I an not a mathematician but it's basic math, all depends on range
Range 0-1: You want to store 4 numbers 0-1 - it's basically binary system
Number1 + Number2 * 2^1 + Number3 * 2^2 + Number4 * 2^3
Range 0-50 You want to store 4 numbers 0-49
Number1 + Number2 * 50^1 + Number3 * 50^2 + Number4 * 50^3
Range 0-X You want to store N numbers 0-X
Number1 + Number2 * (X+1)^1 + Number3 * (X+1)^2 + ... + NumberN * (X+1)^(N-1)
If you have no pattern for your numbers (so it can get compressed in some way) there is really no other way.
It's also super easy for computer to resolve the number unlike the prime numbers
Predetermined values
#FlorainK comment pointed me to fact I missed
(i can decide which numbers)
The only logical solution is give your numbers references
0 is 15342
1 is 6547
2 is 76234
3 is "i like stack overflow"
4 is 42141
so you'll work range 0-4 (5 options) and whatever combination length. Use reference when "encoding" and "decoding" the number
a thousand values?
so you'll work with Range 0-999
0 is 62342
1 is 7456345653
2 is 45656234532
...
998 is 7623452
999 is 4324234326453
Let's say you use 64-bit system and programming/db language that works with 64-bit integers
2^64 = 18446744073709551616
your max range is 1000^X < 18446744073709551616 where X is number of numbers you can store in one single 64-bit integer number
Which is only 6.
You can store only 6 separate numbers 0-999 that will fit one 64-bit integer number.
0,0,0,0,0,0 is 0
1,0,0,0,0,0 is 1
0,1,0,0,0,0 is 1000
999,999,999,999,999,999 is ~1e+18
Ok so you want to store "a,b,c" or "a,b" or "a,b,c,d" or "a" etc. (thanks #FlorianK)
in such case just could use bitwise operators and powers of two
$a = 1 << 0; // 1
$b = 1 << 1; // 2
$c = 1 << 2; // 4
$d = 1 << 3; // 8
.. etc
let's say $flag has $a and $c
$flag = $a | $c; // $flag is integer here
now check it
$ok = ($flag & $a) && ($flag & $c); // true
$ok = ($flag & $a) && ($flag & $b); // false
so in 64 bit system/language/os you can use up to 64 flags which gives you a 2^64 combinations
there is no really other option. prime numbers are much worse for this as you skip many numbers in-between while binary system uses every single number.
I see you are using database and you want to store this in DB.
I really think we are dealing here with XY Problem and you should reconsider your application instead of making such workarounds.
What's the correct way to handle two distinct values being stored in one byte of data. I have a byte that contains two nibbles each containing their own data. I want to read the top nibble and the bottom nibble into their own variables.
11110000 = High 4 bits throttle, to be read into $throttle, and should be a value from 0 to 15.
00001111 = Low 4 bits brake, to be read into $brake, and should be a value from 0 to 15.
Don't forget, drivers can apply the throttle and the brake at the same time, so you might get a value like 11000111. I've myself come up with a solution for the high 4 bits, and it's as simple as pushing the lower 4 bits out of the way with the >> (bit shift right) operator 4 times. $Throttle = $ThrBrk >> 4, but as I can't do that in one move for the lower four bits it looks kinda bad in my source code.
Use ANDoperators for both and shift the top nibble four bits to the right.
$brake = $value & 0x0F;
$throttle = ($value & 0xF0) >> 4;
Check out the & operator, which is a bitwise AND. To get the first (least significant bit), do this:
$lsb = $bits & 1;
So, to get the whole "nibble":
$break = $bits & 15;
What does the << Operator mean in php?
Example:
$t = 5;
$foo = 1 << ($t);
echo($foo);
echo produces: 32
It is the bitwise shift operator. Specifically, the left-shift operator. It takes the left-hand argument and shifts the binary representation to the left by the number of bits specified by the right-hand argument, for example:
1 << 2 = 4
because 1 (decimal) is 1 (binary); left-shift twice makes it 100 which is 4 in decimal.
1 << 5 = 32
because 100000 in binary is 32 in decimal.
Right shift (>>) does the same thing but to the right.
Easy trick to get result of the left shift operation, e.g.
15 << 2 = 15 * (2*2) = 60
15 << 3 = 15 * (2*2*2) = 120
15 << 5 = 15 * (2*2*2*2*2) = 480
and so on..
So it's:
(number on left) multiplied by (number on right) times 2.
Same goes for right shift operator (>>), where:
(number on left) divided by (number on right) times 2
"<<" is a bit-shift left. Please review PHP's bitwise operators. http://php.net/manual/en/language.operators.bitwise.php
A more in-depth explanation:
This means multiply by two because it works on the binary level. For instance, if you have the number 5 in binary
0101
and you bit-shift left once to (move each bit over one position)
1010
then your result is 10. Working with binary (from right to left) is 2^0, 2^1, 2^2, 2^3, and so on. You add the corresponding power of two if you see a 1. So our math for our new result looks like this:
0 + 2^1 + 0 + 2^3
0 + 2 + 0 + 8 = 10
It is the binary shifting operator:
http://php.net/manual/en/language.operators.bitwise.php
<< Bitwise left shift. This operation shifts the left-hand operand’s bits
to the left by a number of positions equal to the right operand,
inserting unset bits in the shifted positions.
>> Bitwise right shift. This operation shifts the left-hand operand’s bits
to the right by a number of positions equal to the right operand,
inserting unset bits in the shifted positions.
NOTE: It’s also interesting to note that these two provide an easy (and very fast)
way of multiply/divide integers by a power of two. For example: 1<<5 will give 32 as a result.......
Consider:
echo 50 >> 4;
Output:
3
Why does it output 3?
50 in binary is 11 0010, shift right by 4 yields 11 which is equal to 3.
See PHP documentation and Wikipedia.
As documented on php.org, the >> operator is a bitwise shift operator which shifts bits to the right:
$a >> $b - Shift the bits of $a $b steps to the right (each step means "divide by two")
50 in binary is 110010, and the >> operator shifts those bits over 4 places in your example code. Although this happens in a single operation, you could think of it in multiple steps like this:
Step 1 - 00011001
Step 2 - 00001100
Step 3 - 00000110
Step 4 - 00000011
Since binary 11 is equal to 3 in decimal, the code outputs 3.
Arithmetic shift right.
The >> operator is called a binary right shift operator.
Shifting bits to the right 4 times is the same as dividing by two, four times in a row. The result, in this case would be 3.125. Since 50 is an int, bit shifting will return the floor of this, which is 3.
Put another way, 50 is 0b110010 in binary. Shifted 4 times we have 0b11, which is 3 in decimal.
>> is the binary right-shift operator.
Your statement shifts the bits in the numeric value 50 four places to the right. Because all integers are represented in two's complement, this equals 3. An easy way to remember this is that one shift to the right is the same as dividing by 2, and one shift to the left is the same as multiplying by 2.
It's called a right shift.
'The bits of the left operand are shifted right by the number of positions of the right operand. The bit positions vacated on the left are filled with the sign bit, and bits shifted out on the right are discarded.'
Information can be found on it here:
http://php.comsci.us/etymology/operator/rightshift.php
It shifts the bits down four places.
50 in binary is 110010.
Shifted down four places is 11, which is 3.
For your convenience, one of the fastest ways to calculate the outputted value from a bitwise shift is to multiply or divide by 2.
For example echo 50 >> 4;
Given that this is a bitwise right, it literally means that the value will be decrease, then we can get the output by divide 50 for 2 and 4 times.
echo 50 >> 4; // 50/(2*2*2*2) ~ 3.
Given that (from) 48 -> (to) 63/16(2*2*2*2), the result will be more than 2 and less than 4. Then
echo 48 >> 4; // 48/(2*2*2*2) ~ 3.
echo 63 >> 4; // 63/(2*2*2*2) ~ 3.
However, when bitwise left, the result will be totally different as it multiplies by 2 with n times:
If echo 50 << 4; // 50*(2*2*2*2) ~ 800
If echo 51 << 4; // 51*(2*2*2*2) ~ 816
Live example: https://3v4l.org/1hbJe
I have the Python expression n <<= 1
How do you express this in PHP?
That statement is short for
n = n << 1;
the << operator is means a bitwise shift left, by n positions. Its counterpart is >>, which means shift right by n. To visualize, say you have the value 5, and you want to shift it left by 2 positions. In binary:
0000 0101 -> 5
shift left by 2:
0001 0100 -> 20
Basically, you shift all bits in the given direction, and pad with zeroes. More or less equivalent, if you don't have a bitwise shift operator (which is common in most, if not all languages), is multiplying by 2^n for shift left, and dividing by 2^n for shift right.
In the example, you can see that: 5 * 2^2 = 5 * 4 = 20.
It's the same operator in php. $n <<= 1;
$n <<= 1; is valid php