I've been looking around and found formula: a = (a + b) - (b = a) it is supposed to swap two variables (or objects in some cases). However I tested it with C++ and php, these gave me different result.
php:
$a = 10;
$b = 20;
$a = ($a + $b) - ($b = $a);
echo $a, " ", $b;
This prints 20 10
C++
int a = 10;
int b = 20;
a = (a + b) - (b = a);
std::cout << a << " " << b;
This prints 10 10
Code looks the same but outputs are different, I've been thinking about two reasons:
C++ code is compiling and php is interpreting.
This formula is useless because it leads to undefined behavior.
Can somebody explains, why C++ and php output differs in this situation?
I'm not sure what the rules are in PHP, but in C++, the order of individual sub-expressions isn't strictly defined, or as the technical term is, it is "unspecified" - in other words, the compiler is allowed to calculate b = a before or after it does a + b. As long as it does a + b and b = a before the subtraction. The use of "unspecified" behaviour allows the compiler to produce more efficient code in some cases, or simply that it's possible to build a compiler for some architectures.
It also means that if you have an expression that "recalculates" a value within the expression itself, and also using it elsewhere in the expression, you get unedefined behaviour (UB for short). UB means just that, the behaviour is not defined - almost anything could happen, including what you are seeing and many other alternatives (e.g. the compiler is allowed to produce 42 as a result as well, even if logic says the answer wouldn't be 42 in this case [it's the wrong question for that!]).
I would also suggest that if you want to swap two values, in PHP:
$t = $a;
$a = $b;
$b = $t;
and in C++:
#include <algorithm>
std::swap(a, b);
or if you insist on writing your own:
int t = a;
a = b;
b = t;
Trying to be clever and perform it "without temporary variable" is almost certainly going to make it slower than the use of a temporary - certainly in a compile language like C++ - in a interpreted language like PHP, creating a new variable may add a bit of extra overhead, but it's unlikely to be that big, compared to the extra effort in the logic required.
C++ code is completely broken because of undefined behavior. (read and write b in one sequence point).
For PHP:
$a = 10;
$b = 20;
$a = ($a + $b) - ($b = $a);
//executes like thus
$a = (30) - ($b = $a);
$a = (30) - ($b = $a = 10); //new $a still not computed, using older $a
$a = (30) - (10);
$a = 20;
//then, $a=20 and $b = 10
This is totally related to Operator Precedence, this might be same in C or might not, it depends on precedence if unexpected behavior not occur.
Related
I am using this PHP routine to calc Pearson Correlation:
function correlation ($x,$y) {
$length = count($x);
$mean1 = array_sum($x)/$length;
$mean2 = array_sum($y)/$length;
$a = $b = 0;
$a2 = $b2 = 0;
$axb = 0;
for ($i = 0; $i < $length; $i++) {
$a = $x[$i]-$mean1;
$b = $y[$i]-$mean2;
$axb +=$a*$b;
$a2 += pow($a,2);
$b2 += pow($b,2);
}
if ($sqrt = sqrt($a2*$b2))
return $axb/$sqrt;
return 0;
}
When I test it for several conditions it returns 0 on exact matchs:
echo correlation([0,0,0,0,0],[0,0,0,0,0]); // Returns 0!!
echo correlation([0,0,0,0,0],[1,1,1,1,1]); // Returns 0!!
echo correlation([1,1,1,1,1],[1,1,1,1,1]); // Returns 0!!
echo correlation([0,0,0,0,0],[9,9,9,9,9]); // Returns 0!!
echo correlation([0,0,0,0,0],[0,1,2,3,4]); // Returns 0 OK
echo correlation([9,9,9,9,9],[0,1,2,3,4]); // Returns 0 OK
echo correlation([0,1,2,3,4],[0,1,2,3,4]); // Returns 1 OK
Why? and How to accomplish that? Thank you!
For info:
A Pearson correlation is a number between -1 and 1 that indicates the
extent to which two variables are linearly related. The Pearson
correlation is also known as the “product moment correlation
coefficient” (PMCC) or simply “correlation”.
Approach 1 (doing at your own):
Using PHP to statistics is a hard path.
First of all, as you're using a weak typed language (you don't need to specify the types on variables), the language can interpret as int so, you need to set all of your variables on type float and execute again to run this. You can have some problems with float in PHP, see here why I talking this: https://3v4l.org/1FU9J
But if you don't mind about high precision, you can modify your precision you can set your round() function or you can set ini_set('precision', 3); to get the precision on your data.
Another thing. If you need precision, you need to use bc extension because floating point in PHP is a problem and can affect your results.
Look more about bc math extension here: https://www.php.net/manual/en/book.bc.php or try to use another language.
Some references about the floating point:
https://www.leaseweb.com/labs/2013/06/the-php-floating-point-precision-is-wrong-by-default/
Problem with Floats! (in PHP)
Approach 2 (using language functions):
And, PHP have some functions to help in this. So, if this isn't a homework to learn or something like this, you can try this: https://www.php.net/manual/en/function.stats-stat-correlation.php
I am running a 64-bit installation of PHP, and from my understanding there is not way to specifically declare a variable as a 32 bit unsigned int.
Using this code as an example:
$test1 = 0x5BE0CD19;
$test2 = 0x3587272B;
$test3 = 0x1F85C98C;
$test4 = 0x428A2F98;
$test5 = 0x61626380;
$test6 = ($test1 + $test2 + $test3 + $test4 + $test5);
Gives me the result 0x154da50e8
Currently I do the following operations to mask variables as 32 bit:
$test6 &= (1 << 32) - 1;
I get my desired result of: 0x54da50e8
For performance reasons, I was wondering, is there a better way to do this without having to use &= (1 << 32) - 1; for every variable in the event of an overflow?
It gets quite cluttered constantly adding the mask to each variable on a per-calculation basis.
Thanks
I have seen a question on stack over flow.
What's happening with this expression? b = a + (a = a + 5)
It shows the value of b will be 15. But when i run this code on Php, value of b is 20.
Why there is difference of output in php and C#
It's happens because PHP and C# differently used memory for save variables.
Read How PHP manages variables.
So PHP not duplicated zval memory for variable "$a" and value of $a changed when ($a = $a +5) has been completed so we have that
$a = 5;
echo $a + ($a = $a + 5); //20
and C# has duplicated memory for a variables read answer What's happening with this expression? b = a + (a = a + 5).
If I try this:
$a = 0;
echo $a + ++$a, PHP_EOL;
echo $a;
I get this output:
2
1
Demo: http://codepad.org/ncVuJtJu
Why is that?
I expect to get this as an output:
1
1
My understanding:
$a = 0; // a === 0
echo $a + ++$a, PHP_EOL; // (0) + (0+1) === 1
echo $a; // a === 1
But why isn't that the output?
All the answers explaining why you get 2 and not 1 are actually wrong. According to the PHP documentation, mixing + and ++ in this manner is undefined behavior, so you could get either 1 or 2. Switching to a different version of PHP may change the result you get, and it would be just as valid.
See example 1, which says:
// mixing ++ and + produces undefined behavior
$a = 1;
echo ++$a + $a++; // may print 4 or 5
Notes:
Operator precedence does not determine the order of evaluation. Operator precedence only determines that the expression $l + ++$l is parsed as $l + (++$l), but doesn't determine if the left or right operand of the + operator is evaluated first. If the left operand is evaluated first, the result would be 0+1, and if the right operand is evaluated first, the result would be 1+1.
Operator associativity also does not determine order of evaluation. That the + operator has left associativity only determines that $a+$b+$c is evaluated as ($a+$b)+$c. It does not determine in what order a single operator's operands are evaluated.
Also relevant: On this bug report regarding another expression with undefined results, a PHP developer says: "We make no guarantee about the order of evaluation [...], just as C doesn't. Can you point to any place on the documentation where it's stated that the first operand is evaluated first?"
A preincrement operator "++" takes place before the rest of the expression it's in evaluates. So it is actually:
echo $l + ++$l; // (1) + (0+1) === 2
a + b
a = 1
b = ++a
:= 2
Why do you expect something else?
In PHP:
$a = 0;
$c = $a + ++$a;
Operator precedence visualized:
$c = ($a) + (++$a);
Evaluation sequence visualized:
$a = 0; ($a = 0)
$a = 1; (++$a)
$c = $a + $a (1 + 1);
Or written out:
The moment the sum operation is performed, $a is already 1 because ++$a has been already evaluated. The ++ operator is evaluated before the + operator.
For the fun:
$a++ + ++$a
Results in 2, too. However if you compare it as an expression, it's not equal:
$a++ + ++$a == $a + ++$a
Where as
$a++ + ++$a == $a-- + --$a
is "equal".
See Also:
Order of evaluation in PHP (Sep 2013; by NikiC) (via)
My Evaluation Order in PHP blog post explain this in detail, but here is the basic idea:
Operator precedence and associativity have nothing to do with evaluation order.
PHP does not guarantee an evaluation order. The order can change between PHP versions without notice and can also be different depending on the surrounding code.
"Normally" PHP will evaluate left-to-right, with the exception of accesses to "simple" variables (like $a). Accesses to simple variables will be executed after more complex expressions, regardless in which order the expressions actually occur.
In this particular case it means that ++$a is run first because it is a complex expression and only then the value of $a is fetched (it is already 1 at this point). So effectively you are summing 1 + 1 = 2.
The reason that simple variables are fetched after complex expressions is the Compiled Variables (CV) optimization. If you disable this optimization, for example by using the # error suppression operator, all expressions are evaluated left-to-right, including simple variable fetches.
In this particular case it means that #($a + ++$a) will result in 1, because first $a is fetched (0 at that time) and incremented only after that.
++ is the higher precedence operator, so it gets applied first.
So now l = 1.
So 1 + 1 = 2.
When you do your ++$l (preincrement), it will be done before your addition -> check operator precedence).
So, the value of $l will be 1 before your addition :
echo $l + ++$l; // $l => 1 because ++$l is done first
So your answer will be 2.
But when you do :
echo $l // you will get your first value which is $l => 1
So your answer will be 1.
This behaviour can be confirmed by inspecting how PHP compiles your script, for example:
$a = 0;
echo $a + ++$a;
Compiles into the following opcodes, which are then executed:
compiled vars: !0 = $a
line # * op fetch ext return operands
---------------------------------------------------------------------------------
1 0 > ASSIGN !0, 0
1 PRE_INC $1 !0
2 ADD ~2 !0, $1
3 ECHO ~2
4 > RETURN null
This translates to the following equivalent script:
$a = 0; // ASSIGN
$tmp = ++$a; // PRE_INC
echo $a + $tmp; // ADD, ECHO
Conclusion
By the time $a is evaluated as the left hand expression of $a + (++$a), it has already been incremented, because ++$a was evaluated first.
Obviously, this behaviour should not be relied upon; in any language for that matter.
Check the increment operator manual:
http://www.php.net/manual/en/language.operators.increment.php
Or see this codepad: http://codepad.org/Y3CnhiLx
<?php
$n = 0;
$m = 0;
echo '++ before:';
echo $n+ ++$n;
echo PHP_EOL;
echo '++ after:';
echo $m+ $m++;
echo PHP_EOL;
echo 'n:'.$n;
echo PHP_EOL;
echo 'm:'.$m;
Outputs:
++ before:2
++ after:1
n:1
m:1
As you may know we have two increment operator, one is pre-increment and second is post-increment. Pre-increment increase the value of integer before it use in expression, on the other hand post increment increase value of number after it used in expression.
suppose you have variable $a and variable $b as below
$a=0;
$b=++$a gives the value of b=1
while
$b=$a++ gives the value b=0
The output of your code varies with PHP version as seen here
Output for 4.3.0 - 5.0.5
1
1
In the above case the left hand side of + operator is evaluated first (0, 1, +).
Output for 5.1.0 - 5.5.0alpha4
2
1
In the above case the right hand side of + operator is evaluated first (1, 1, +).
This is in accordance with interjay's answer that in PHP there is no guarantee about the order of evaluation of sub-expresions. The assumption that the output could be 1, 1 is correct, so are that answers that claim that the output could be 1, 2.
First obvious part is that ++ have higher priority than +.
Second part is that php engine doesn't store value from first operand into another anonymous variable. So $l + ++$l is not an qeuivalent for
$a = $l;
$b = ++$l;
return $a + $b;
As mentioned before there is a difference in x++ and ++x. You can interpret it in the way that
x++;
increments after the semicolon
and
++x;
increments on evaluation of the expression
So it seems that your expression is evaluated from right to left
echo $l + ++$l;
Get $l: $l = 0
Apply ++: ++$l = 1
Get $l: $l = 1
Apply +: $l + $l = 1 + 1 = 2
All statements are executed from right to left.
So the value is first incremented than the value of your variable is = 1 so 1+1=2
I'm getting some odd results where 2 identical functions (one in PHP and one in javascript) are returning different results.
The input for both of these lines of code is identical:
a = 4653896912;
b = 13;
I have double checked the variable types and both variables are numbers in JS and integers in PHP.
The line of code for PHP is this:
$a = $a >> $b;
For Javascript it's this:
a = a >> b;
You'd expect a to have the same value after both, but I'm getting the following:
PHP: $a = 568102
JS: a = 43814
Which has completely baffled me at this point.
Turns out this is definitely an issue of PHP using 64 bit integers and JS only using 32 bit. The problem I face now is that I need to get PHP to use 32-bit integers for these calculations. I found a function someone else wrote that looks like it should work, but it doesn't seem to be changing the output at all for me.
private static function toInt32(&$x) {
$z = hexdec(80000000);
$y = (int) $x;
if($y ==- $z && $x <- $z){
$y = (int) ((-1) * $x);
$y = (-1) * $y;
}
$x = $y;
}
The below code demonstrates masking the upper 32 bits of the number to retrieve only the lower 32 bits to use in your calculations. 4294967295 is 2^32 - 1. I think that if you mask all values that could be greater than 32 bits in this manner, then you can get the same results from your php and javascript.
<?php
$php_a = 4653896912;
$php_b = 13;
//convert $php_a into a 32 bit val
$php_a = $php_a & 4294967295;
$a = $php_a >> $php_b;
echo "PHP: \$a = $a <br />";
?>
<script type="text/javascript">
var a = 4653896912;
var b = 13;
var a = a >> b;
alert('Javascript A value is ' + a);
</script>
4653896912 is more than 32 bits.. unpredictable results are likely. I get $a = 43814 for PHP, but that is actually 358929617 >> 13, so in all likelihood PHP is doing 64 bit operations but JavaScript is only 32 bit.
I believe it's because you're a is above the limit of a 32-bit signed integer for [PHP][1].
The highest value possible is about 2 million, and a is over 4 billion.
When you're rolling over because of space limitations, results can be unpredictable (or at least, very difficult to figure out).
If your server is on a 64-bit version of PHP then it'll max out much higher than than, but javascript is limited by what the end-user is running.
You can read up on PHP on their integers page.