Why is the answer 15 here? - php

For the following code snippet the answer is 15.
$a = '5 USD';
$b = 10;
echo $a + $b;
But in the variable $a, if 5 is in between 'USD' or after 'USD' the output is 10. Why is it so?

From php.net:
When a string is evaluated in a numeric context, the resulting value
and type are determined as follows.
If the string does not contain any of the characters '.', 'e', or 'E'
and the numeric value fits into integer type limits (as defined by
PHP_INT_MAX), the string will be evaluated as an integer. In all other
cases it will be evaluated as a float.
The value is given by the initial portion of the string. If the string
starts with valid numeric data, this will be the value used.
Otherwise, the value will be 0 (zero). Valid numeric data is an
optional sign, followed by one or more digits (optionally containing a
decimal point), followed by an optional exponent. The exponent is an
'e' or 'E' followed by one or more digits.
Literally:
$a + $b means numeric + numeric.
"5 USD" starts with a valid numeric data, so PHP converts it into 5.
"USD 5" or "U5SD" starts with not valid numeric data, so PHP converts it into 0.
UPDv1:
<?php
header('Content-Type: text/plain');
function plus($a, $b){
echo $a, ' + ', $b, ' = ', $a + $b, PHP_EOL;
}
plus('5 frogs', 3); // 5 + 3 = 8
plus('frogs: 5', 3); // 0 + 3 = 3
plus('f5rogs', 3); // 0 (not HEX) + 3 = 3
plus('0xF5', 3); // 245 (HEX) + 3 = 248
plus('0011b', 3); // 11 (not BIN) + 3 = 14
plus('1E5', '1.2xx'); // 100000 (FLOAT) + 1.2 (FLOAT) = 100001.2
plus('true', 2); // 0 (not BOOL) + 2 = 2
?>
Also, check out this: php string number concatenation messed up.
UPDv2:
There is "no way" for PHP to typecast string value to octal, regardless of zero-fill effect. Still, as mentioned before, PHP able to typecast string to hexadecimal.
<?php
header('Content-Type: text/plain');
function plus($a, $b){
echo $a, ' + ', $b, ' = ', $a + $b, PHP_EOL;
}
plus(008, 12); // Invalid octal, PHP assumes it is 0. Result: 12.
plus('008', 12); // Invalid octal? No, it is decimal. Result: 20.
plus(0x0F, 1); // Valid hexadecimal. Result: 16.
plus('0x0F', 1); // Valid hexadecimal. Result: 16.
plus('0x0X', 1); // Invalid hexadecimal, PHP assumes it is 0. Result: 1.
?>
It is not mentioned in "string to number conversion" docs.

See PHP Manual Language.types.string.conversion
String conversion to numbers
When a string is evaluated in a numeric context, the resulting value and type are determined as follows.
If the string does not contain any of the characters '.', 'e', or 'E' and the numeric value fits into integer type limits (as defined by PHP_INT_MAX), the string will be evaluated as an integer. In all other cases it will be evaluated as a float.
The value is given by the initial portion of the string. If the string starts with valid numeric data, this will be the value used. Otherwise, the value will be 0 (zero). Valid numeric data is an optional sign, followed by one or more digits (optionally containing a decimal point), followed by an optional exponent. The exponent is an 'e' or 'E' followed by one or more digits.
Examples can be found in the manual (link above)
$foo = 1 + "bob-1.3e3"; // $foo is integer (1)
$foo = 1 + "bob3"; // $foo is integer (1)
$foo = 1 + "10 Small Pigs"; // $foo is integer (11)
Answering your question
$a = '5 USD'; // The string starts with number, so by an implicit cast to int, it will be 5
$b = 10;
echo $a + $b; // = 15
In the other example you wrote
$a = 'USD 5'; // The string does not start with a number, so by an implicit cast to int, it will be 0
$b = 10;
echo $a + $b; // = 10
For more information on this conversion, see the Unix manual page for strtod(3).

Because
php > echo (int)"a";
0
So if you feed the PHP executable with
php > "USD 5" + "10"
it will cast both operands to integers:
php > (int)"USD 5" + (int)"10"
And thus you will receive result of 0 + 10.

Related

Why only hex recognized but not octal and byte if the left hand operand is a number in an expression

First expression:
displays 123 octal, is not recognized, if recognized it should be 83
Second Expression:
displays 291, here hex recognized, if not recognized it should be 123
Third Expression:
Displays 0
$y = 0+"0123";
echo $y;
echo '<br>';
$x = 0+"0x123";
echo $x;
echo '<br>';
$x = 0+"0b10101";
echo $x; // This displays 0
output:
123
291
0
See the documentation at http://php.net/manual/en/language.types.string.php#language.types.string.conversion
The value is given by the initial portion of the string. If the string
starts with valid numeric data, this will be the value used.
Otherwise, the value will be 0 (zero). Valid numeric data is an
optional sign, followed by one or more digits (optionally containing a
decimal point), followed by an optional exponent. The exponent is an
'e' or 'E' followed by one or more digits.
There is no mention of non-decimal support.
PHP casting of strings to numbers is limited (and probably with good reason). If you want to use different base numbers you need to specify them as numbers e.g.
$y = 0123;
echo $y; // 83
$x = 0x123;
echo $x; // 291
$x = 0b10101;
echo $x; // 21
Notice that they are not quoted.
If you want to explicitly convert strings you need to do the following:
echo octdec("0123"); // 83
echo hexdec("0x123"); // 291
echo bindec("0b10101"); // 21
The prefixes (e.g. 0 or 0x or 0b) are allowed but optional when using these functions.
Note: PHP used to support implicit casting of hex strings as numbers but as of 7.0 it does not

PHP string to decimal with .00

so I am trying to achieve this
I have decimal 1.00 Which when i convert to float becomes 1.0. So my question is how can i save the last zero and at the same time to be float not a string if i use number_format(1.0,2) it becomes "1.00" Which is string but i need to be decimal with the last zero. This is what i tried so far
<?php
$decimal = "1.0";
$decimalToFloat = floatval($decimal) // It becomes 1.0
$decimalToFloat = number_format($decimal,2) // It becomes "1.00" !!! String not a float !!!
// The result which i want is 1.00 not "1.00"
Let me start by saying that this is an XY problem, as you don't need to convert from a string to an integer in PHP, as PHP will coerce the type for you automatically.
In addition to this, there is no need to specify the number of places on a decimal, as 1 is exactly equal to 1.0, and 1.0 is exactly equal to 1.00. In fact, forcibly casting the string showcases that PHP will automatically trim the decimal places:
$decimal = "1.0";
echo number_format((float)$decimal, 2, '.', ''); // "1.00" (string)
echo (int)number_format((float)$decimal, 2, '.', ''); // 1 (int)
echo (float)number_format((float)$decimal, 2, '.', ''); // 1 (float)
It is impossible to showcase an int or float with decimal places comprised purely of zeros in PHP. Though you do not need to do this; you can simply use the whole numbers instead:
echo 1 + 1.01; // 2.01 (float)
Hope this helps! :)

Typecasting on bitwise operators

Can anyone explain why I have different output for the two bitwise operation in the code below?
According to the php documentation at http://php.net/manual/en/language.operators.bitwise.php, $value should typecast to an integer:
Both operands and the result for the << and >> operators are always treated as integers.
My code:
$value = 4294967295;
echo 'value is float: ' . (($value >> 32 - 1) & 1); //OUTPUT: value is string: 1
$value = '4294967295';
echo 'value is string: ' . (($value >> 32 - 1) & 1); //OUTPUT: value is string: 0
Does typecasting for the second operation not work, since unsigned integers aren't supported and the operation is performed on the ASCII values of the characters?
If so, why does it work with the float value?
My code works fine with the float value, so I have no real problem, but I would like to understand what is happening. It took me a while to figure out, where my code didn't behave as expected.
I use php version 5.4.19 on Windows 7 x64 (for testing).
This is an explanation of what appears to be happening. PHP 5.3.18, windows XP, 32 bit.
The code:
$value = 4294967295; // This is a 'float'
$vint = (int) $value; // this becomes -1 as an integer.
// shows the types and values
var_dump($value, $vint, dechex($vint));
echo 'value is float: ' . (($value >> 32 - 1) & 1); //OUTPUT: value is string: 1
The output:
float 4294967295
int -1
string 'ffffffff' (length=8)
value is float: 1
Note that the 'float' is converted to integer -1, which is all bits on. Hence the output result when shifted.
Now lets look at the other result:
The code:
$value = '4294967295'; // is treated as positive?
var_dump($value, dechex($value));
echo 'value is string: ' . (($value >> 32 - 1) & 1); //OUTPUT: value is string: 0
The output:
string '4294967295' (length=10)
string '7fffffff' (length=8)
value is string: 0
The interesting point here is that the 'sign' bit is 'off' when converted to an integer. This explains the output when shifted.

php variable magic. How php work with decimal and hex

$a1 = 010;
print (int)$a1;
print value = 8
Anybody can explain how php made this result?
Because 010 in hex = 16.
010 is 10 in base-8, i.e. 8 in base-10.
Full reference from the manual:
<?php
$a = 1234; // decimal number
$a = -123; // a negative number
$a = 0123; // octal number (equivalent to 83 decimal)
$a = 0x1A; // hexadecimal number (equivalent to 26 decimal)
$a = 0b11111111; // binary number (equivalent to 255 decimal)
?>
It's not hex. It's octal.
For HEX:
$a = 0x10;
For octal
$a = 010;
For HEX number, you have to start with 0x.

Any Difference Between (int) 1 and 1 in PHP?

I was reading some code that a consultant provided us. It's a bit convoluted, and at the end of a function, it reads:
return (int) 1;
Instead of:
return 1;
PHP has a lot of magic in it; is this as bone-headed as it looks, or is there a valid reason to cast an integer as an integer?
No, it's the same. 1 is an integer literal.
See here these are all integer literals; casting to int has no effect:
$a = 1234; // decimal number
$a = -123; // a negative number
$a = 0123; // octal number (equivalent to 83 decimal)
$a = 0x1A; // hexadecimal number (equivalent to 26 decimal)
If you did return "1"; that would be an entirely different matter. There are some differences in behaviour between "1" (string) and 1 (int), namely with bitwise operators.
It's pretty bone headed. Integer literals are, well... integers.
1 === 1 however 1 !== '1'
also, when necessary, (as in this case it definitely isn't) I would suggest not typecasting with (int) use intval() instead.

Categories