In PHP, what does (int) really do? - php

I understand that casting with (int) rounds a number towards zero, but then I started poking around with bases other than 10 and now I'm not exactly sure what else (int) does:
$a = 050; // an octal number
echo $a; // output is ----> 40
however
$a = '050';
echo (int)$a; // output is ----> 50
So I thought (int) besides rounding towards zero also clips leading zeroes. But then if I do the same exercise as in the second code block (above) with binary I don't get what I expect:
$a = '0b010';
echo (int)$a; // output is ----> 0
and in hexadecimal:
$a = '0x050';
echo (int)$a; // output is ----> 0
Even using decimal scientific notation gives a quizzical result:
$a = 5e6;
$b = '5e6';
echo $a; // output is ----> 5000000
echo (int)$b; // output is ----> 5
What does casting to an integer using (int) really mean? Besides stripping the decimal point and everything after in a float, does (int) parse a cast string character-by-character, and return the concatenation of all leading, numeric, non-zero characters? Like this:
function intCast($str) {
$length = strlen($str);
$returnVal = '';
for($i = 0; $i < $length; $i++) {
// Note: ord() values 48 to 57 represent 0 through 9
if ($returnVal === '' && ord($str[$i]) == 48) {
continue; // leading zeroes are OK but don't concatenate
} else if (ord($str[$i]) > 48 && ord($str[$i]) < 58) {
$returnVal .= $str[$i];
} else {
break;
}
}
return (strlen($returnVal) > 0) ? $returnVal : 0;
}
***Note that this link does not seem to provide a sufficient answer.

'050' is a string, and PHP's first job in doing a typecast is to normalize that string:
echo '050' + 1 -> echo '50' + 1 -> echo 50 + 1 -> echo 51 -> 51
050 by itself is an octal number, it's already an integer, so the only thing PHP has to do is convert it to a base10 number for output:
echo 050 + 1 -> echo 40 + 1 -> echo 41 -> 41

Related

PHP strcmp result int meaning

In php, there is a built-in function strcmp to compare if two strings are same or not.
Returning value is integer number that if the first parameter is greater than the second I get > 0, if not < 0 and if the same 0.
So the part I don't get is comparing string as number.
Does PHP convert string to number and if so how's PHP converting?
$a = 'acorn';
$b = 'zebra';
var_dump( strcmp($a, $b) ); // -25 <- what's this number? seems like alphabetical position...nnn
Doesn't it really matter what number I get, shall I just take what it is?
Looking at the PHP: strcmp doc :
Returns < 0 if str1 is less than str2; > 0 if str1 is greater than
str2, and 0 if they are equal.
So yes, you can use it as it is to compare your string.
But if you want to understand the number returned by the function, it depend on the characters that makes the strings.
In ASCII :
A=65 < B=66 < C=67 ....
So if the string are different, one is gonna be greater than the other.
So you can also test it easily with a short script :
<?php
$a='A';
$b='B';
$c='C';
//Return -1 because $a is smaller than $b by one (65 < 66 )
echo strcmp($a,$b);
//Return -2 because $a is smaller than $c by two (65 < 67 )
echo strcmp($a,$c);
//Return -1 because $b is smaller than $c by one (66 < 67 )
echo strcmp($b,$c);
//Return 1 because $c is greater than $b by one (67 > 66 )
echo strcmp($c,$b);
//Return 2 because $c is greater than $a by two (67 > 65 )
echo strcmp($c,$a);
strcmp is using for comparing two strings in PHP.
If your result is greater the 0 its mean variable one ($a) is greater then Var2($b)
if return result is less then 0 its mean $b is greater and If result is equal to 0 its mean both strings are equal to each other.
$a="Hello world!";
$b= "Hello world!";
var_dump(strcmp($a, $b)); // result is 0
$a = "Hello";
$b = "Hello World";
var_dump(strcmp($a, $b)); // Outputs: -6
and If you want to see difference then you can use this
$a = 'some-content-here-example';
$b = 'some-content-example';
$asp = preg_split('//', $a, -1);
$bsp = preg_split('//', $b, -1);
$l1 = count($asp);
$l2 = count($bsp);
$length = $l1;
if ($l2 > $l1) {
$length = $l2;
}
$record = null;
$x = null;
for ($x = 0; $x < $length; $x++) {
if ($a[$x] != $b[$x]) {
if (!isset($a[$x])) {
$record.= $b[$x];
} else {
$record.= $a[$x];
}
}
}
echo $record;

generating same number with the given length

I have this math assignment that I should make into code.
I've tried all I thought of but I couldn't find a solution.
All this should be done without using php functions, only math operations.
You can use while, for, and such...
So I have number for example 9
Now I should create number of the length 9 which would be 999999999
If I had, for example, number 3, then the result should be 333.
Any ideas?
$gen = -1;
while($highest > 0) {
$gen = $highest + ($highest * 10);
$highest = $highest - 1;
}
echo $gen;
Here is a method that does not build a string; it uses pure math. (There will be many, many ways to do this task)
$x=9;
$result=0;
for($i=$x; $i; --$i){ // this looping expression can be structured however you wish potato-potatoe
$result+=$x*(10**($i-1)); // x times (10 to the power of (i-1))
}
echo $result;
// 999999999
*note: ** acts like pow() if you want to look it up.
Late edit: here is a clever, little loopless method (quietly proud). I am only calling range() and foreach() to demo; it is not an integral component of my method.
Demo: https://3v4l.org/GIjfG
foreach(range(0,9) as $n){
// echo "$n -> ",(integer)(1/9*$n*(10**$n)-($n/10)),"\n";
// echo "$n -> ",(1/9*$n*(10**$n)-(1/9*$n)),"\n";
// echo "$n -> ",(int)(1/9*10**$n)*$n,"\n";
// echo "$n -> ",(int)(10**$n/9)*$n,"\n";
echo "$n -> ",(10**$n-1)/9*$n,"\n";
}
Output:
0 -> 0
1 -> 1
2 -> 22
3 -> 333
4 -> 4444
5 -> 55555
6 -> 666666
7 -> 7777777
8 -> 88888888
9 -> 999999999
1/9 is the hero of this method because it generates .111111111(repeating). From this float number, I am using 10**$n to "shift" just enough 1s to the left side of the decimal point, then multiplying this float number by $n, then the float must be converted to an integer to complete.
Per #axiac's comment, the new hero is 10**$n-1 which generates a series of nines to the desired length (no float numbers). Next divide the nines by nine to generate a series of ones which becomes the perfect multiplier. Finally, multiply the series of ones and the input number to arrive at the desired output.
There are two operations you need to accomplish:
given a number $number, append the digit $n to it;
repeat operation #1 some number of times ($n times).
Operation #1 is easy:
$number = $number * 10 + $n;
Operation #2 is even easier:
for ($i = 0; $i < $n; $i ++)
What else do you need?
Initialization of the variable used to store the computed number:
$number = 0;
Put them in order and you get:
// The input digit
// It gives the length of the computed number
// and also its digits
$n = 8;
// The number we compute
$number = 0;
// Put the digit $n at the end of $number, $n times
for ($i = 0; $i < $n; $i ++) {
$number = $number * 10 + $n;
}
// That's all
If intval() is accepted:
$result = '';
$input = 9;
for($i=0; $i < $input; $i++){
$result .= $input;
}
$result = intval($result);
else:
$result = 0;
$input = 9;
for($i=0; $i < $input; $i++){
$factor = 1;
for($j = 0; $j < $i; $j++){
$factor *= 10;
}
$result += $input * $factor;
}
=>
9 + 90 + 900 + 9000 + 90000...

Format number to N significant digits in PHP

I would like to format (round) float (double) numbers to lets say 2 significant digits for example like this:
1 => 1
11 => 11
111 => 110
119 => 120
0.11 => 0.11
0.00011 => 0.00011
0.000111 => 0.00011
So the arbitrary precision remains same
I expect there is some nice function for it already built in, but could not find any so far
I was pointed to How to round down to the nearest significant figure in php, which is close but doesn't work for N significant digits and I'm not sure what it does with 0.000XXX numbers
To get a number rounded to n significant figures you need to find the size of the number in powers of ten, and subtract that from n.
This works fine for simple rounding:
function sigFig($value, $digits)
{
if ($value == 0) {
$decimalPlaces = $digits - 1;
} elseif ($value < 0) {
$decimalPlaces = $digits - floor(log10($value * -1)) - 1;
} else {
$decimalPlaces = $digits - floor(log10($value)) - 1;
}
$answer = round($value, $decimalPlaces);
return $answer;
}
This will give the following:
0.0001234567 returns 0.0001235
123456.7 returns 123500
However a value such as 10 to four significant figures should strictly be represented as 10.00 to signify the precision to which the value is known.
If this is the desired output you can use the following:
function sigFig($value, $digits)
{
if ($value == 0) {
$decimalPlaces = $digits - 1;
} elseif ($value < 0) {
$decimalPlaces = $digits - floor(log10($value * -1)) - 1;
} else {
$decimalPlaces = $digits - floor(log10($value)) - 1;
}
$answer = ($decimalPlaces > 0) ?
number_format($value, $decimalPlaces) : round($value, $decimalPlaces);
return $answer;
}
Now 1 is displayed as 1.000
With little modification to possible duplicate, answer by Todd Chaffee:
public static function roundRate($rate, $digits)
{
$mod = pow(10, intval(round(log10($rate))));
$mod = $mod / pow(10, $digits);
$answer = ((int)($rate / $mod)) * $mod;
return $answer;
}
To make sigFig(0.9995, 3) output 1.00, use
if(floor(log10($value)) !== floor(log10(round($value, $decimalPlaces)))) {$decimalPlaces--;}
Said line of code should be placed before declaring $answer.
If input $value is negative, set a flag and remove the sign at the beginning of the function, like this:
if($value < 0){$flag = 1;}
$value = ltrim($value, "-");
Then right before returning $answer, detect if the flag is set and if so restore the negative sign, like this:
if(isset($flag)){$answer = "-".$answer;}
Finally, for result values with ambiguous number of significant digits (e.g., 1000, 12000,...), express the result in scientific notation to the desired number of significant digits using sprintf or printf.

Is this expression a PHP bug? 6227020800 % 10 = 4

Writing some code connected with factorials (counting sum of numbers of factorial) I noticed that 13! modulus 10 equals 4.
function fact($n)
{
if ($n == 0) return 1;
return $n * fact($n-1);
}
function sum_num($n)
{
$sum = 0;
while ($n > 0)
{
$sum = $sum + ($n % 10);
$n = floor($n/10);
}
return $sum;
}
$n = 13;
$buff = fact($n);
echo $n."! = ".$buff;
echo "<br>";
echo "Summ ".$n."! = ".sum_num($buff);
Output is:
13! = 6227020800
Summ 13! = 31
But Summ should be 27. I begun search and found that on the first step I am getting 4 instead 0.
6227020800 % 10 = 4
And I don't understand why?
6227020800 requires 33 bits. The most siginficant bit gets truncated and you get you the number 1932053504 (modulo 10 of which is 4).
For arbitrary precision math use bc* functions, e.g. bcmod(6227020800, 10).
May be you should use bcmath php module instead for this operations.
http://php.net/manual/en/book.bc.php
Just take care that this module uses strings as inputs.
I'm pretty sure, you use a 32-bit version. Here the max value is 4.294.967.296.

PHP - Get length of digits in a number

I would like to ask how I can get the length of digits in an Integer. For example:
$num = 245354;
$numlength = mb_strlen($num);
$numlength should be 6 in this example. Somehow I can't manage it to work?
Thanks
EDIT: The example code above --^ and its respective method mb_strlen(); works just fine.
Maybe:
$num = 245354;
$numlength = strlen((string)$num);
Accepted answer won't work with the big numbers. The better way to calculate the length of any number is to invoke floor(log10($num) + 1) with a check for 0.
$num = 12357;
echo $num !== 0 ? floor(log10($num) + 1) : 1; // prints 5
It has multiple advantages. It's faster, you don't do the casting of types, it works on big numbers, it works with different number systems like bin, hex, oct.
The equation does the logarithm with base 10 then makes the floor of it and adds 1.
This solution can work independently on the base, so if you want to calculate the length of binary or hex just change the base of the logarithm.
Working fiddle
The accepted solution presents a problem when evaluating negative numbers.
It works with a positive number:
$num = 245354;
$numlength = strlen((string)$num);
// Result: 6
But with a negative number, the (-) is added to the count:
$num = -245354;
$numlength = strlen((string)$num);
// Result: 7
Quick workaround:
$num = -245354;
$numlength = strlen((string)abs($num));
// Result: 6
More elegant way :)
ceil(log10($num));
You could also use some basic math!
$digits = (int)(log($num,10)+1)
<?php
$num = 123;
$num2 = 1234;
$num3 = 12345;
function digits($num){
return (int) (log($num, 10) + 1);
}
echo "\n $num: " . digits($num); // 123: 3
echo "\n $num2:" . digits($num2); // 1234: 4
echo "\n $num3:" . digits($num3); // 12345: 5
echo "\n";
Another way to find out the length of a number in digits would be to divide the integer part of the number to 10 until it becomes 0.
Example:
2021/10 = 202.1
202/10 = 20.2
20/10 = 2
2/10 = 0.2
Code:
function numberGetLength($number) {
$count = 0;
while (intval($number) > 0) {
$number = intval($number) / 10;
$count += 1;
}
return $count
}
Just using some version of (int)(log($num,10)+1) fails for 10, 100, 1000, etc. It counts the number 10 as 1 digit, 100 as two digits, etc. It also fails with 0 or any negative number.
If you must use math (and the number is non-negative), use:
$numlength = (int)(log($num+1, 10)+1);
Or for a math solution that counts the digits in positive OR negative numbers:
$numlength = ($num>=0) ? (int)(log($num+1, 10)+1) : (int)(log(1-$num, 10)+1);
But the strlen solution is just about as fast in PHP.
In PHP types are loosely set and guessed, if you want to see something as a string if it is an integer, float, and (i have not tried this) bool then #Gorjunav is the most correct answer.
Reset the variable as a string
$stringNum = (string) $num;
Then you can go anything string related you want with it! And vice-versa for changing a string to an int
$number = (int) $stringNum;
and so on...
count only integer value
`<?php
$n1 =12345;
$n2 =123454.55;
$n3 =12345564.557;
echo "The Number you Type: ".$n1."<br>";
$count = 0;
while ($n1 != 0)
{
$n1 = $n1 / 10;
$n1 = intval($n1);
++$count;
}
echo "The Digit in a Number: ".$count;
}
?>`
echo strlen((string) abs($num)); // using **abs** it'll work with negative integers as well
Tested in PHP 4.4.9 - 8.0.0
$array = array(-1, 0, -0, 1, 4, 9, 10, -10, 20, -20, 100, -100);
foreach( $array as $key => $num ){
echo $key."\t{$num}\t=>\t".($num !== 0 ? floor(log10(abs($num)) + 1) : 1)."\n";
}
/* Output:
0 -1 => 1
1 0 => 1
2 0 => 1
3 1 => 1
4 4 => 1
5 9 => 1
6 10 => 2
7 -10 => 2
8 20 => 2
9 -20 => 2
10 100 => 3
11 -100 => 3
*/
The following function work for either integers or floats (works with PHP7+):
function digitsCount($number): int
{
$number = abs($number);
$numberParts = explode(".", $number);
return
strlen($numberParts[0]) +
(strlen($numberParts[1] ?? 0));
}

Categories