&= yields false on even numbers - php

I've stumbled upon something odd, and I can't find any answers anywhere. &= seems to interpret even numbers as false. Is there a logical explanation for this, or is this a bug?
This snippet reproduces the problem, at least on my setup:
$nums = array(1,2,3,4,5,6,7,8,9,10);
$var1 = true;
$var2 = true;
foreach ($nums as $num) {
// Test
$var1 &= $num;
$var2 = $var2 && $num;
echo "$var1, $var2<br />";
//Reset
$var1 = true;
$var2 = true;
}
System: PHP Version 5.3.10-1ubuntu3.4

If I understand your question correctly, you are confusing Bitwise AND (&) with Logical AND (&&). No, they are not the same.
Bitwise operations are best understood if you inspect the binary representation of numbers. Here is what happens with even/odd numbers:
/* 1 & 0 */ 00000001b & 00000000b // 00000000b
/* 1 & 1 */ 00000001b & 00000001b // 00000001b
/* 1 & 2 */ 00000001b & 00000010b // 00000000b
/* 1 & 3 */ 00000001b & 00000011b // 00000001b
For logical operations, you simply need to look at the truthiness of operands:
1 && 0 // false -- 0 is falsy
1 && 1 // true -- any non-zero number is truthy
1 && 2 // true
1 && 3 // true

You are doing a bitwise AND on the numbers.
The numbers in binary are...
1 => 0001
2 => 0010
3 => 0011
4 => 0100
5 => 0101
6 => 0110
7 => 0111
8 => 1000
9 => 1001
10 => 1010
Realise that when you increment the number, the least significant digit is always changing, and since you're ANDing with 1, it will look like the even numbers are false as the result is 0 (0000 & 1 is 0).

Related

Is the number the power of 2 - without using log10 ? PHP

I'm new to PHP
I was taking coding challenge and I stumbled on this
piece of code :
// check whether a given positive integer is a power of two.
The solution
function is_Power_of_two($n)
{
if(($n & ($n - 1)) == 0)
{
return "$n is power of 2";
}
else
{
return "$n is not power of 2";
}
}
print_r(is_Power_of_two(4)."\n");
print_r(is_Power_of_two(128)."\n");
print_r(is_Power_of_two(16)."\n");
In the if section, what is happening there ?
let's say $n = 2
2 & 2 - 1 == 0 // replaced $n with num
2 & 1 == 0 ? // results , What ?
EDIT :
So basicly
& isn't a logical operator
It is a bitwise Operator
Bitwise operators allow evaluation and manipulation of specific bits
within an integer.
You can check this video that I found very helpful it will show you how bit's work and how you can work with bitwise
https://www.youtube.com/watch?v=2U-bh4gSn1k
And thanks to : kollol
now I get why the solution code return only the power of two values
Also thanks to :
lars-stegelitz
kiko-software
if both digits are same vertically then the value will be 1, 0 otherwise
for example
2 & 16 = (binary of 2) & (binary of 16)
00010 & 10000
= 00000 = 0
(2) 00010
(16) 10000
------------------
00000
now suppose
2 & 18 = (binary of 2) & (binary of 18)
00010 & 10010
(2) 00010
(18) 10010
----------------------
00010 = not 0
logic is all the numbers which are power of two will always get a 0 in bitwise and operation with 2. Rest will not .

How bitwise operator works [duplicate]

This question already has answers here:
What are bitwise operators?
(9 answers)
Closed 7 years ago.
I dont get how the following codes work?
function odd($var){
return ($var & 1);
}
echo odd(4); /* returns and print 0 */
echo odd(5); /* returns and print 1 */
this function returns true if argument is an odd number
and returns false if argument is an even number. How it works ?
Odd numbers in binary always have a least-significant bit (LSB) of 1. That is why your code
function odd($var){
return ($var & 1);
}
returns true on odd numbers. Here are your examples from your question:
(decimal) 4 & 1 = (binary) 100 & 001 = (binary) 000 = (decimal) 0 = false
(decimal) 5 & 1 = (binary) 101 & 001 = (binary) 001 = (decimal) 1 = true
Another way to think of it is
100 (decimal 4) - an even number
AND 001 (decimal 1)
= 000 (decimal 0) - return false
and
101 (decimal 5) - an odd number
AND 001 (decimal 1)
= 001 (decimal 1) - return true
bitwise comparison already says what it does: it compares the numbers bit by bit.
If we take 4 bits, the bit representation of 4 is: 0100. The bit representation of 5 is 0101. When we compare this with & (and), it returns the bits which are both set.
0100 & 0001 = 0000 (no bits are the same)
0101 & 0001 = 0001 (only Least Significant Bit (LSB) is 1)
It is masking off all bits except 0. & is the and operator. And 1 is 000000000001 in binary. So it works as it is named.

Logic behind php if code

I'm trying to understand this code in the company's system that I am working in but this doesn't make any sense for me.
$k = 48;
if (($k & 2) > 0) {
echo "2 is true";
}
echo "<br />";
if (($k & 4) > 0) {
echo "4 is true";
}
echo "<br />";
if (($k & 8) > 0) {
echo "8 is true";
}
echo "<br />";
if (($k & 16) > 0) {
echo "16 is true";
}
echo "<br />";
if (($k & 32) > 0) {
echo "32 is true";
}
When $k is 10 or 11, both 2 and 8 is true.
When $k is 12 or 13, both 4 and 8 is true.
Please help me figure this out
This code is simply checking if certain bit positions are set in some value $k. See how bitwise airthmetic works.
In the code you've sent us, it doesn't have much context. However, this is a typical pattern for checking values in a bitmask.
In general, however, the > 0 is unnecessary (since anything !0 typically == true).
It is important to note that when I say bit positions, I mean of the binary number. That is, $k & 32 does not check bit number 32, it instead checks the 6th most significant bit (32d == 0b100000).
Short example
Consider the last statement. We already determined that decimal 32 looks like 100000 in binary. Now say that we want to check whether or not the 6th bit is set in some number 33. 33 is represented as 0b100001 in binary. Now we take the bitwise and which works much like multiplication that we're used to seeing in base 10 (i.e. decimal).
0b100000 <--- decimal 32
&
0b100001 <--- decimal 33
--------
0b100000 <--- Result is > 0 and, therefore, this value has the 6th bit set
Now, let's retry this example with a different number. How about decimal 15.
0b100000 <--- decimal 32
&
0b001111 <--- decimal 15
--------
0b000000 <--- Result == 0 and, therefore, the 6th bit is not set
Now, this & (not to be confused with logical and which is represented as &&) works for multiple bits as well. Say you want to check for bits 6 and 4, then you would want to use 0b101000 (decimal 40), but depending on what you wanted to test (i.e. exactly those bits or just one of those bits), your conditional may change.
Just a little bit more
From a style standpoint it is important to note that these masks are typically represented in hexadecimal instead of decimal (or binary because that would be cumbersome). This is mostly because it is somewhat unclear what binary representation a decimal number correlates to when looking at it "at-a-glance." Let us again consider decimal 32. In hexadecimal, a binary number can be represented as a hexadecimal number by simply grouping bits by 4's (from right to left). See below
0b100000 <--- decimal 32
0000 === 0x0 (hexadecimal 0)
10 === 0b0010 (implied leading 0's) === 0x2 (hexadecimal 2)
--------
0x20
As you can see, hex 20 is decimal 32 is binary 100000.
In your code there are just some bitwise AND operation which checks if some bits are set or not.
So if we take a look what's going on in the first one:
$k = 48;
if (($k & 2) > 0) {
echo "2 is true";
}
The expression ($k & 2) a bit more readable:
0011 0000 $k
0000 0010 2
------------ &
0000 0000 = 0
So if (0 > 0) is false
And another example:
if (($k & 16) > 0) {
echo "16 is true";
}
The expression ($k & 16) a bit more readable:
0011 0000 $k
0001 0000 16
------------ &
0001 0000 = 16
So if (16 > 0) is true
FYI information:
Bitwise AND operation table:
A | B | Result
--------------------
0 | 0 | 0
0 | 1 | 0
1 | 0 | 0
1 | 1 | 1
And as a reference to the manual here: http://php.net/manual/en/language.operators.bitwise.php

Odd and Even numbers (using & or %)

I've always used the following in order to find even and odd numbers:
if( $num % 2 ) { echo "odd"; }
if( !($num % 2) ) { echo "even"; }
But recently I stumbled upon with the following code that works exactly the same:
if( $num & 1 ) { echo "odd"; }
if( !($num & 1) ) { echo "even; }
What's the logic behind the "&" in the second method?
I went to check the PHP: Arithmetic Operators and the ampersand is not part of the options.
Thanks.
It is the bitwise-AND operator. Remember that in the computer, every integer is stored in binary form, and the lowest-significance binary digit is 2^0 == 1. So, every odd number will have the lowest binary digit = 1.
So, the bitwise AND operator compares your value bit-by-bit with the constant 1. Bits that are 1 in both operands are set to 1 in the result, but bits that are 0 in either operand are set to 0 in the result. The final result (which will be either 1 or 0) is coerced to boolean by PHP because you are using it as the clause in an if() statement.
There is a very good reason for checking evenness with & instead of %: Speed! The % operator requires a division operation so the remainder can be calculated, which is computationally much, much more expensive than just comparing the bits directly.
An example:
$num = 9; // 9 == 8 + 1 == 2^3 + 2^0 == 1001b
echo (string)($num & 1); // 1001b & 0001b = 0001b - prints '1'
$num = 10; // 10 == 8 + 2 == 2^3 + 2^1 == 1010b
echo (string)($num & 1); // 1010b & 0001b = 0000b - prints '0'
& is the binary AND.
The binary value of an odd number AND 1 will be 1, and the binary value of an even number AND 1 will be 0.
This happens because the binary value of an odd number always ends with 1 and the binary value of an even number ends with 0. So...
10101101 & 00000001 = 00000001 in the case of an odd number and,
10101100 & 00000000 = 00000000 in the case of an even number.

Pipe sign in PHP Code

I wanted to concatenate 2 variables, and by error I typed another code and I got a strange result.
This is what looks like the code :
echo 'Hello World' | 'test';
Result : |e|o World
What the pipe sign do if not concatenated ?
According to the PHP manual
"|" is a "bitwise OR". Bitwise operators allow evaluation and manipulation of specific bits within an integer.
Example Name Result
$a | $b Or (inclusive or) Bits that are set in either $a or $b are set.
Example:
$a = 9;
$b = 10;
echo $a | $b;
This would output the number 11 as follows:
1 Byte ( 8 bits )
Place Value 128 64 32 16 8 4 2 1
$a 0 0 0 0 1 0 0 1 = 9
$b 0 0 0 0 1 0 1 0 = 10
$a | $b 0 0 0 0 1 0 1 1 = 11
If you notice we have 3 bits set, in the 8, 2, and 1 column.. add those up 8+2+1 and you get 11.
For mere string concatenation use the dot . operator.
Hope that clarifies it.
It's the OR bitwise operator
If you want to concat string you should use dot
echo "ABC" . "DEF";
Example of OR bitwise usage
// base 16 - result in 0x03
$result = 0x01 | 0x02;
// base 2
0000 0001
0000 0010
---------
0000 0011
That | means 'bitwise OR', which will convert the strings into binary, then overlay them on each other to calculate the result using logical OR for each position i.e. if either string has a 1 at that position, then the result will have a 1, otherwise, you'll get a 0.
In this case, it's doing this with the numerical ascii character codes of each character, which sometimes leads to new character codes and sometimes to garbage, which won't render. This is why the beginning of 'Hello world' is messed up, where it is overlaid with 'test', but the end is fine because it's not having any 1s added to it by another string at that point. See here for a more detailed example from the manual (uses XOR, but same idea).
Use . for concatenation.
I would guess that it's a bitwise OR

Categories