PHP check if variable is a whole number

后端 未结 20 1231
感动是毒
感动是毒 2020-12-29 20:05

I have this PHP code:

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

What i want to know is, how to check whether $

20条回答
  •  长情又很酷
    2020-12-29 20:29

    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
    

提交回复
热议问题