开发者

PHP check if variable is a whole number

开发者 https://www.devze.com 2022-12-19 03:53 出处:网络
I have this PHP code: $entityEl开发者_开发知识库ementCount = (-($highScore-$totalKeywordCount))/0.29;

I have this PHP code:

$entityEl开发者_开发知识库ementCount = (-($highScore-$totalKeywordCount))/0.29;

What i want to know is, how to check whether $entityElementCount is a whole number (2, 6, ...) or partial (2.33, 6.2, ...).

Thank you!


if (floor($number) == $number)


I know this is old, but I thought I'd share something I just found:

Use fmod and check for 0

$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
if (fmod($entityElementCount,1) !== 0.0) {
    echo 'Not a whole number!';
} else {
    echo 'A whole number!';
}

fmod is different from % because if you have a fraction, % doesn't seem to work for me (it returns 0...for example, echo 9.4 % 1; will output 0). With fmod, you'll get the fraction portion. For example:

echo fmod(9.4, 1);

Will output 0.4


$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
if (ctype_digit($entityElementCount) ){
    // (ctype_digit((string)$entityElementCount))  // as advised.
    print "whole number\n";
}else{
    print "not whole number\n";
}


I would use intval function like this:

if($number === intval($number)) {

}

Tests:

var_dump(10 === intval(10));     // prints "bool(true)"
var_dump("10" === intval("10")); // prints "bool(false)"
var_dump(10.5 === intval(10.5)); // prints "bool(false)"
var_dump("0x539" === intval("0x539")); // prints "bool(false)"

Other solutions

1)

if(floor($number) == $number) {   // Currently most upvoted solution: 

Tests:

$number = true;
var_dump(floor($number) == $number); // prints "bool(true)" which is incorrect.

2)

if (is_numeric($number) && floor($number) == $number) {

Corner case:

$number = "0x539";
var_dump(is_numeric($number) && floor($number) == $number); // prints "bool(true)" which depend on context may or may not be what you want

3)

if (ctype_digit($number)) {

Tests:

var_dump(ctype_digit("0x539")); // prints "bool(false)"
var_dump(ctype_digit(10)); // prints "bool(false)"
var_dump(ctype_digit(0x53)); // prints "bool(false)"


The basic way, as Chacha said is

if (floor($number) == $number)

However, floating point types cannot accurately store numbers, which means that 1 might be stored as 0.999999997. This will of course mean the above check will fail, because it will be rounded down to 0, even though for your purposes it is close enough to 1 to be considered a whole number. Therefore try something like this:

if (abs($number - round($number)) < 0.0001)


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!";


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


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))


    $num = 2.0000000000001;
    if( $num == floor( $num  ) ){
        echo('whole');
    }else{
        echo('fraction');
    }

EX:

2.0000000000001 | fraction

2.1 | fraction

2.00 | whole

2 | whole


(string)floor($pecahformat[3])!=(string)$pecahformat[3]


Another hacky way I came up with is ceil($value) === floor($value). If a number is a whole number, this should always be true, even if comparing 10 with 10.000 and will even work with numbers cast in string, for example ceil("10.0") === floor(10).


floor($entityElementCount) == $entityElementCount

This will be true if this is a whole number


This is not an attempt to answer this question so much. Their are plenty of answer already. If you are doing statistics as the question implies I suspect @antonio-vinicius-menezes-medei answer will suite you best. However I needed this answer for input validation. I found this check more reliable for validating an input string is a whole number:

is_numeric($number) && preg_match('/^[0-9]+$/', $number)

The 'is_numeric' simply corrects for "true" converting to "1" in preg_match.

So playing off of @antonio-vinicius-menezes-medei answer. I wrote a script to test this below. Note the ini_set('precision', 20). preg_match will convert the argument to a string. If your precicion is set below the length of the float values they will simply round at the given precision. Similar to @antonio-vinicius-menezes-medei answer this precision setting will force a similar estimation length.

  ini_set('precision', 20);
  $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);

  foreach ($test_cases as $number)
  {
    echo '<strong>';
    var_dump($number);
    echo '</strong>';
    echo boolFormater(is_numeric($number) && preg_match('/^[0-9]+$/', $number));
    echo '<br>';
  }

  function boolFormater($value)
  {
    if ($value)
    {
      return 'Yes';
    }
    return 'No';
  }

Which produces this output:

float(0.28999999999999998002) No
int(2) Yes
int(6) Yes
float(2.3300000000000000711) No
float(6.2000000000000001776) No
string(5) "10.00" No
float(1.3999999999999999112) No
int(10) Yes
string(2) "10" Yes
float(10.5) No
string(5) "0x539" No
bool(true) No
bool(false) No
int(83) Yes
float(9.4000000000000003553) No
string(3) "ten" No
string(3) "100" Yes
int(1) Yes
float(0.99999999699999997382) No
int(0) Yes
float(0.00010000000000000000479) No
float(1) Yes
float(0.99999990000000005264) No
float(2.0000000000000004441) No


improved version of @Tyler Carter's solution, which handles edge cases better than the original:

function is_whole_number($number){
    return (is_float(($f=filter_var($number,FILTER_VALIDATE_FLOAT))) && floor($f)===$f);    
}

(Tyler's code fail to recognize that the string "123foobar" is not a whole number. this improved version won't make that mistake. credits to @Shafizadeh in the comments for discovering the bug. also this is php7 strict_types=1-compatible)


What seems a simple approach would be to use modulus (%) to determine if a value is whole or not.

x = y % 1  

if y is anything other then a whole number the result is not a zero (0). A test then would be:

if (y % 1 == 0) { 
   // this is a whole number  
} else { 
   // this is not a whole number 
}

var isWhole = (y % 1 == 0? true: false);  // to get a boolean return. 

Granted this will view a negative number as a whole number, then then just wrap ABS() around y to always test on the positive.


I always use typecasting to check if variables contain a whole number, handy when you don't know the origin or type of the value.

if ((string) $var === (string) (int) $var) {
    echo 'whole number';
} else {
    echo 'whatever it is, it\'s something else';
}

In your particular case, I would use is_int()

if (is_int($var) {
    echo 'integer';
}


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.


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.


I know this is a super old post but this is a simple function that will return a valid whole number and cast it to an int. Returns false if it fails.

function isWholeNumber($v)
{
    if ($v !='' && is_numeric($v) && strpos($v, '.') === false) {
        return (int)$v;
    }
    return false;
}

Usage :

$a = 43;
$b = 4.3;
$c = 'four_three';

isWholeNumber($a) // 43
isWholeNumber($b) // false
isWholeNumber($c) // false


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;
}


$entityElementCount = (-($highScore-$totalKeywordCount))/0.29;

Method 1-
    By using ctype_digit() function. 

    if ( ctype_digit($entityElementCount )) { 
        echo "Whole Number\n"; 
    } else { 
        echo "Not a whole Number\n"; 
    } 


Method 2-
    By using is_float() function. 

    if (is_float($entityElementCount )) { 
        echo "Not a Whole Number\n"; 
    } else { 
        echo "Whole Number\n"; 
    } 


Method 3-
    By using is_int() function. 

    if (is_int($entityElementCount )) { 
        echo "Whole Number\n"; 
    } else { 
        echo "Not a whole Number\n"; 
    } 


Method 5-
    By using fmod() function. 

    It needs 2 parameters one dividend and other is divisor
    Here $dividend=$entityElementCount and divisor=1
    if (fmod($dividend,$divisor) !== 0.0) {
        echo 'Not a whole number!';
    } else {
     echo 'A whole number!';
    }

there are some more function like intval(), floor(),... can be used to check it`enter code here`
0

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号