I have this PHP code:
$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
What i want to know is, how to check whether $
I tested all the proposed solutions with many problematic values mentioned, they all fail for at least one of the test cases. Start checking if $value
is a number using is_numeric($value)
reduces the number of failures for many solutions, but does not turn any solution into an ultimate one:
$test_cases = array(0.29, 2, 6, 2.33, 6.2, '10.00', 1.4, 10, "10", 10.5, "0x539", true,
false, 0x53, 9.4, "ten", "100", 1, 0.999999997, 0, 0.0001, 1.0, 0.9999999,
(-(4.42-5))/0.29);
function is_whole_number($value) {
// Doing this prevents failing for values like true or "ten"
if (!is_numeric($value)) {
return false;
}
// @ghostdog74's solution fails for "10.00"
// return (ctype_digit((string) $value));
// Both @Maurice's solutions fails for "10.00"
// return ((string) $value === (string) (int) $value);
// return is_int($value);
// @j.hull's solution always returns true for numeric values
// return (abs($value) % 1 == 0 ? true : false);
// @ MartyIX's solution fails for "10.00"
// return ($value === intval($value));
// This one fails for (-(4.42-5))/0.29
// return (floor($value) == $value);
// This one fails for 2
// return ctype_digit($value);
// I didn't understand Josh Crozier's answer
// @joseph4tw's solution fails for (-(4.42-5))/0.29
// return !(fmod($value, 1) != 0);
// If you are unsure about the double negation, doing this way produces the same
// results:
// return (fmod($value, 1) == 0);
// Doing this way, it always returns false
// return (fmod($value, 1) === 0);
// @Anthony's solution fails for "10.00"
// return (is_numeric($value) && is_int($value));
// @Aistina's solution fails for 0.999999997
// return (abs($value - round($value)) < 0.0001);
// @Notinlist's solution fails for 0.999999997
// return (round($value, 3) == round($value));
}
foreach ($test_cases as $test_case) {
var_dump($test_case);
echo ' is a whole number? ';
echo is_whole_number($test_case) ? 'yes' : 'no';
echo "\n";
}
I think that solutions like the ones proposed by @Aistina and @Notinlist are the best ones, because they use an error threshold to decide whether a value is a whole number. It is important to note that they worked as expected for the expression (-(4.42-5))/0.29
, while all the others failed in that test case.
I decided to use @Notinlist's solution because of its readability:
function is_whole_number($value) {
return (is_numeric($value) && (round($value, 3) == round($value)));
}
I need to test if values are whole numbers, currency or percentage, I think 2 digits of precision is enough, so @Notinlist's solution fits my needs.
Running this test:
$test_cases = array(0.29, 2, 6, 2.33, 6.2, '10.00', 1.4, 10, "10", 10.5, "0x539", true,
false, 0x53, 9.4, "ten", "100", 1, 0.999999997, 0, 0.0001, 1.0, 0.9999999,
(-(4.42-5))/0.29);
function is_whole_number($value) {
return (is_numeric($value) && (round($value, 3) == round($value)));
}
foreach ($test_cases as $test_case) {
var_dump($test_case);
echo ' is a whole number? ';
echo is_whole_number($test_case) ? 'yes' : 'no';
echo "\n";
}
Produces the following output:
float(0.29)
is a whole number? no
int(2)
is a whole number? yes
int(6)
is a whole number? yes
float(2.33)
is a whole number? no
float(6.2)
is a whole number? no
string(5) "10.00"
is a whole number? yes
float(1.4)
is a whole number? no
int(10)
is a whole number? yes
string(2) "10"
is a whole number? yes
float(10.5)
is a whole number? no
string(5) "0x539"
is a whole number? yes
bool(true)
is a whole number? no
bool(false)
is a whole number? no
int(83)
is a whole number? yes
float(9.4)
is a whole number? no
string(3) "ten"
is a whole number? no
string(3) "100"
is a whole number? yes
int(1)
is a whole number? yes
float(0.999999997)
is a whole number? yes
int(0)
is a whole number? yes
float(0.0001)
is a whole number? yes
float(1)
is a whole number? yes
float(0.9999999)
is a whole number? yes
float(2)
is a whole number? yes
Just to share my solution with localized string/number, this combo worked like a charm for me.
public static function isWholeNumber ($input, $decimalDelimiter = ',')
{
if (is_string($input)){
$input = str_replace($decimalDelimiter, '.', $input);
$input = floatval($input);
}
if (fmod($input,1) !== 0.0) {
return false;
}
return true;
}
if(floor($number) == $number)
Is not a stable algorithm. When a value is matematically 1.0 the numerical value can be 0.9999999. If you apply floor() on it it will be 0 which is not equals to 0.9999999.
You have to guess a precision radius for example 3 digits
if(round($number,3) == round($number))
function isInteger($value)
{
// '1' + 0 == int, '1.2' + 0 == float, '1e2' == float
return is_numeric($value) && is_int($value + 0);
}
function isWholeNumber($value)
{
return is_numeric($value)
&& (is_int($value + 0)
|| (intval($value + 0) === intval(ceil($value + 0))));
}
If you want to check for both whole and decimal numbers, you can do the following:
if (isInteger($foo))
{
// integer as int or string
}
if (isWholeNumber($foo))
{
// integer as int or string, or float/double with zero decimal part
}
else if (is_numeric($foo))
{
// decimal number - still numeric, but not int
}
This will correctly check your number without rounding it, casting it to int (which in the case of a decimal number will lose the decimal part), or doing any math. If, however, you want to treat 1.00
as a whole number, then that's a whole another story.
If you know that it will be numeric (meaning it won't ever be a an integer cast as a string, like "ten"
or "100"
, you can just use is_int()
:
$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
$entityWholeNumber = is_int($entityElementCount);
echo ($entityWholeNumber) ? "Whole Number!" : "Not a whole number!";
A simple solution for positive whole numbers only. This may not work for everything.
$string = '0x539';
$ceil = ceil($string);
if($ceil < 1){
$ceil = FALSE; // or whatever you want i.e 0 or 1
}
echo $ceil; // 1337
You can use floor() instead of ceil() if so desired.