Any Difference Between (int) 1 and 1 in PHP? - 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.

Related

why does is_infinite() returns TRUE for the string '592e5399'?

<?php
$number1 = 1;
$number2 = 0;
$number3 = $number1/$number2 ;
$number3 will return float(INF) which is OK.
var_dump($number3 );
in order to identify INF, I can use is_infinite like below.
$check_Is_INF = is_infinite($number3);
$check_Is_INF above will return true - which is OK.
var_dump($check_Is_INF );
But why does this always return TRUE if I check this string: 592e5399, like below
$number3 = '592e5399';
$check_Is_INF = is_infinite($number3);
var_dump($check_Is_INF );
As in the documentation for is_infinite:
Returns TRUE if val is infinite (positive or negative), like the
result of log(0) or any value too big to fit into a float on this
platform.
The number 592e5399 is in notation expression (because of the e that it contains), so it's a very huge number exceeding the float limit. Because of that it will be considered an infinite number.
Precisely, the e means ^ so the number will be 592 ^ 5399.
A note about the type of the variable $number3:
you set it as String but thanks to the PHP's Type Juggling, every value you use in an expression, will assume the type accordingly to the context when is it. In this case, the String is converted in number because the function is_infinite expects a number.
Because PHP is casting the string into a float
Function description from https://www.php.net/is_infinite
is_infinite ( float $val ) : bool
It doesn't matter if you call
is_infinite('592e5399')
is_infinite(592e5399)
Both will be cast to float, and you'll get the same response: true.

rand(0,$var) returns zero when $var is really big

When I run the code below:
<?
echo rand(0, 0xfffffffffffffbff);
echo rand(0, 0xfffffffffffffc00);
echo rand(0, $something_bigger_than_0xfffffffffffffbff);
I got something like:
-828
0
0
(the 2nd and 3rd number will always be zero)
mt_rand() has the same behavior.
so, why zero?
rand() function takes two integers as its arguments. Integers usually have the maximum range of 2^32. The supplied argument, when converted to integers, will be larger than this, hence causing an integer overflow.
This is actually documented behavior. From the PHP manual documentation:
When converting from float to integer, the number will be rounded
towards zero.
If the float is beyond the boundaries of integer (usually +/- 2.15e+9
= 2^31 on 32-bit platforms and +/- 9.22e+18 = 2^63 on 64-bit platforms), the result is undefined, since the float doesn't have
enough precision to give an exact integer result. No warning, not even
a notice will be issued when this happens!
You need to pass integer value to the rand() as the above $a = 0xfffffffffffffbff; is a double but not an integer value, the double value 0xfffffffffffffbff will be cast to an integer and eventually you will be getting a zero.
An illustration for your understanding.
<?php
$a = 0xfffffffffffffbff;
echo gettype($a); //"prints" double
if(is_int($a))
{
echo "Yes";
}
else
{
echo "Nope.. casting that to int results in..".intval($a)."<br>";
}
echo rand(0, $a);
OUTPUT :
double
Nope.. casting that to int results in..0
0

How do I truncate a decimal in PHP?

I know of the PHP function floor() but that doesn't work how I want it to in negative numbers.
This is how floor works
floor( 1234.567); // 1234
floor(-1234.567); // -1235
This is what I WANT
truncate( 1234.567); // 1234
truncate(-1234.567); // -1234
Is there a PHP function that will return -1234?
I know I could do this but I'm hoping for a single built-in function
$num = -1234.567;
echo $num >= 0 ? floor($num) : ceil($num);
Yes intval
intval(1234.567);
intval(-1234.567);
Truncate floats with specific precision:
echo bcdiv(2.56789, 1, 1); // 2.5
echo bcdiv(2.56789, 1, 3); // 2.567
echo bcdiv(-2.56789, 1, 1); // -2.5
echo bcdiv(-2.56789, 1, 3); // -2.567
This method solve the problem with round() function.
Also you can use typecasting (no need to use functions),
(int) 1234.567; // 1234
(int) -1234.567; // -1234
http://php.net/manual/en/language.types.type-juggling.php
You can see the difference between intval and (int) typecasting from here.
another hack is using prefix ~~ :
echo ~~1234.567; // 1234
echo ~~-1234.567; // 1234
it's simpler and faster
Tilde ~ is bitwise NOT operator in PHP and Javascript
Double tilde(~) is a quick way to cast variable as integer, where it is called 'two tildes' to indicate a form of double negation.
It removes everything after the decimal point because the bitwise operators implicitly convert their operands to signed 32-bit integers. This works whether the operands are (floating-point) numbers or strings, and the result is a number
reference:
https://en.wikipedia.org/wiki/Double_tilde
What does ~~ ("double tilde") do in Javascript?
you can use intval(number); but if your number bigger than 2147483648 (and your machine/os is x64) all bigs will be truncated to 2147483648. So you can use
if($number < 0 )
$res = round($number);
else
$res = floor($number);
echo $res;
You can shift the decimal to the desired place, intval, and shift back:
function truncate($number, $precision = 0) {
// warning: precision is limited by the size of the int type
$shift = pow(10, $precision);
return intval($number * $shift)/$shift;
}
Note the warning about size of int -- this is because $number is potentially being multiplied by a large number ($shift) which could make the resulting number too large to be stored as an integer type. Possibly converting to floating point might be better.
You could get fancy with a $base parameter, and sending that to intval(...).
Could (should) also get fancy with error/bounds checking.
An alternative approach would be to treat number as a string, find the decimal point and do a substring at the appropriate place after the decimal based on the desired precision. Relatively speaking, that won't be fast.

PHP, Convert any number to float 0.x

I need to do this rather strange thing, let's say i have:
$number = rand(1, 9);
(This is just an example of what number it could be, in reality i get it in entirely different way)
And now i need "convert" that number to 0.2 or whatever number i got, basically it has to begin with 0 and be a float type of number.
PHP does not support explicit type casting in variable declaration. To convert the int to a float in the way you want to simply divide by 10:
$number = rand(1, 9) / 10;
See this page on PHP Type Juggling for more info. If you mix floats and ints or other types they will be re-casted. Exmple:
echo 10 + 2.5; // gives you 12.5, a float because of the types used
Edit: PHP does have explicit type casting, just not in variable declaration. But even if you cast an integer as a float, it won't display with a decimal place. To do that use PHP's number_format function instead:
echo number_format(10, 1); // gives you 10.0
Edit 2: If you simply want to make your number a decimal between 0 and 1 (such that 2 becomes 0.2, 25 becomes 0.25, etc.) you could use the following function:
function getNumAsDecimal($num) {
return ($num / pow(10, strlen((string)$num)));
}
So getNumAsDecimal(2) would return 0.2.
function Floatize(){
return (float) (rand(1, 9) / 10);
}
echo Floatize(); // will return something like 0.2 or 0.5 or 0.9
$number=(float)rand(1, 9)/10;
See PHP type casting.

What would be the best way to detect if a float has a zero fraction value (e.g. 125.00) in PHP?

See, I want to write a function that takes a float number parameter and rounds the float to the nearest currency value (a float with two decimal places) but if the float parameter has a zero fraction (that is, all zeroes behind the decimal place) then it returns the float as an integer (or i.e. truncates the decimal part since they're all zeroes anyways.).
However, I'm finding that I can't figure out how to determine if if a fraction has a zero fraction. I don't know if there's a PHP function that already does this. I've looked. The best I can think of is to convert the float number into an integer by casting it first and then subtract the integer part from the float and then check if the difference equals to zero or not.
if($value == round($value))
{
//no decimal, go ahead and truncate.
}
This example compares the value to itself, rounded to 0 decimal places. If the value rounded is the same as the value, you've got no decimal fraction. Plain and simple.
A little trick with PHPs type juggling abilities
if ($a == (int) $a) {
// $a has a zero fraction value
}
I think the best way:
if ((string)$value == (int)$value){
...
}
Example:
$value = 2.22 * 100;
var_dump($value == (int)$value); // false - WRONG!
var_dump($value == round($value)); // false - WRONG!
var_dump((string)$value == (int)$value); // true - OK!
function whatyouneed($number) {
$decimals = 2;
printf("%.".($number == (int)($number) ? '0' : $decimals)."F", $number);
}
So basically it's either printf("%.2F") if you want 2 decimals and printf("%.2F") if you want none.
Well, the problem is that floats aren't exact. Read here if you're interested in finding out why. What I would do is decide on a level of accuracy, for example, 3 decimal places, and base exactness on that. To do that, you multiply it by 1000, cast it to an int, and then check if $your_number % 1000==0.
$mynumber = round($mynumber *1000);
if ($mynumber % 1000==0)
{ isInt() }
Just so you know, you don't have to write a function to do that, there's already one that exists:
$roundedFloat = (float)number_format("1234.1264", 2, ".", ""); // 1234.13
If you want to keep the trailing .00, just omit the float cast (although it will return a string):
$roundedFloatStr = number_format("1234.000", 2, ".", ""); // 1234.00

Categories