Is there a straightforward way of determining the number of decimal places in a(n) integer/double value in PHP? (that is, without using explode
)
<?php
test(0);
test(1);
test(1.234567890);
test(-123.14);
test(1234567890);
test(12345.67890);
function test($f) {
echo "f = $f\n";
echo "i = ".getIntCount($f)."\n";
echo "d = ".getDecCount($f)."\n";
echo "\n";
}
function getIntCount($f) {
if ($f === 0) {
return 1;
} elseif ($f < 0) {
return getIntCount(-$f);
} else {
return floor(log10(floor($f))) + 1;
}
}
function getDecCount($f) {
$num = 0;
while (true) {
if ((string)$f === (string)round($f)) {
break;
}
if (is_infinite($f)) {
break;
}
$f *= 10;
$num++;
}
return $num;
}
Outputs:
f = 0
i = 1
d = 0
f = 1
i = 1
d = 0
f = 1.23456789
i = 1
d = 8
f = -123.14
i = 3
d = 2
f = 1234567890
i = 10
d = 0
f = 12345.6789
i = 5
d = 4
$num = "12.1234555";
print strlen(preg_replace("/.*\./", "", $num)); // 7
Pattern .*\.
means all the characters before the decimal point with its.
In this case it's string with three characters: 12.
preg_replace
function converts these cached characters to an empty string ""
(second parameter).
In this case we get this string: 1234555
strlen
function counts the number of characters in the retained string.
How about this?:
$iDecimals = strlen($sFull%1);
function numberOfDecimals($value)
{
if ((int)$value == $value)
{
return 0;
}
else if (! is_numeric($value))
{
// throw new Exception('numberOfDecimals: ' . $value . ' is not a number!');
return false;
}
return strlen($value) - strrpos($value, '.') - 1;
}
/* test and proof */
function test($value)
{
printf("Testing [%s] : %d decimals\n", $value, numberOfDecimals($value));
}
foreach(array(1, 1.1, 1.22, 123.456, 0, 1.0, '1.0', 'not a number') as $value)
{
test($value);
}
Outputs:
Testing [1] : 0 decimals
Testing [1.1] : 1 decimals
Testing [1.22] : 2 decimals
Testing [123.456] : 3 decimals
Testing [0] : 0 decimals
Testing [1] : 0 decimals
Testing [1.0] : 0 decimals
Testing [not a number] : 0 decimals
Integers do not have decimal digits, so the answer is always zero.
Double or float numbers are approximations. So they do not have a defined count of decimal digits.
A small example:
$number = 12.00000000012;
$frac = $number - (int)$number;
var_dump($number);
var_dump($frac);
Output:
float(12.00000000012)
float(1.2000000992884E-10)
You can see two problems here, the second number is using the scientific representation and it is not exactly 1.2E-10.
For a string that contains a integer/float you can search for the decimal point:
$string = '12.00000000012';
$delimiterPosition = strrpos($string, '.');
var_dump(
$delimiterPosition === FALSE ? 0 : strlen($string) - 1 - $delimiterPosition
);
Output:
int(11)
You could try casting it to an int, subtracting that from your number and then counting what's left.