【问题标题】:PHP check if variable is a whole numberPHP检查变量是否为整数
【发布时间】:2011-01-12 10:04:10
【问题描述】:

我有这个 PHP 代码:

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

我想知道的是,如何检查 $entityElementCount 是整数 (2, 6, ...) 还是部分 (2.33, 6.2, ...)。 p>

谢谢!

【问题讨论】:

    标签: php integer double numbers


    【解决方案1】:
    if (floor($number) == $number)
    

    【讨论】:

    • 试试这个,$number = (-(4.42-5))/0.29;经过计算$number = 2,但上面的条件无法判断它是一个整数
    • 在 $number 上尝试 var_dump。这是一个浮动,这就是为什么这不起作用。浮点数不精确。
    • 正确的用法是 if(is_numeric($number) && floor($number) == $number) ... 因为 floor('banana') == 'banana' 是真的。
    • 我想知道为什么这么多票。如果我发布了这个答案,我会删除它。
    • @Shafizadeh 好点。犯了一个improved version 不会犯那个错误
    【解决方案2】:

    我知道这是旧的,但我想我会分享我刚刚发现的东西:

    使用fmod 并检查 0

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

    fmod 与 % 不同,因为如果你有一个分数,% 似乎对我不起作用(它返回 0...例如,echo 9.4 % 1; 将输出 0)。使用 fmod,您将获得小数部分。例如:

    echo fmod(9.4, 1);

    将输出0.4

    【讨论】:

    • @Flavius 谢谢!在接受答案后,我以这种方式发布。我只是把它放在这里,因为我认为它非常有用。随着时间的推移,它可能会得到像你这样的人更多的支持:)
    • 这个答案似乎是最好的。
    • 如果您想按照大多数安全顾问的建议进行类型匹配(===!==),fmod 返回一个浮点数,因此您需要执行以下操作:fmod($a, 1) === 0.0 以确保它是一个整数。不过,我也不完全确定这是否准确。不幸的是 fmod 返回一个浮点数。
    • @danielson317 感谢您的提示。多年来我没有接触过 PHP,所以我没有意识到它有那种类型的相等运算符。至于不幸的是fmod返回一个浮点数,怎么会?返回一个浮点数是函数的目的(fmod = "float modules")。另外,我测试了你的理论,你是对的,它需要是`!== 0.0`。我会更新答案。
    • @Joseph 浮点数本质上是一个估计数字。如果它返回一个双精度表达式,则可以保证表达式是准确的,而浮点数可能看起来像 0.0,甚至打印为 0.0 但不是===0.0,这是由于处理过程中的一些估计。实际上,PHP 并不是为货币而设计的,这实际上会有所作为。请记住,准确度可能会根据 php.ini 中的precision 而发生变化
    【解决方案3】:
    $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";
    }
    

    【讨论】:

    • 对不起,我匆忙回答。您只需在使用 ctype_digit 函数之前将 $entityElementCount 转换为字符串,以使上述代码正常工作。
    • 所以,如果 (ctype_digit((string)$entityElementCount)) 应该这样做。
    • 注意:ctype_digit('10.00') 将返回 FALSE,在此示例中表示“不是整数”
    • @Philipp 你能尝试打破我的解决方案吗?
    【解决方案4】:

    我会像这样使用intval 函数:

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

    测试:

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

    其他解决方案

    1)

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

    测试:

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

    2)

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

    转角案例:

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

    测试:

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

    【讨论】:

      【解决方案5】:

      基本的方式,正如茶茶所说的那样

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

      但是,浮点类型不能准确存储数字,这意味着 1 可能存储为 0.999999997。这当然意味着上述检查将失败,因为它将向下舍入为 0,即使出于您的目的它足够接近到 1 以被视为整数。因此尝试这样的事情:

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

      【讨论】:

      • 我会说这是最好的解决方案,考虑到浮动的性质。只需选择适合您任务的精度级别即可。
      • 在“123foobar”上失败(它认为 123foobar 是一个整数) - 我真的很喜欢精确度调整
      【解决方案6】:

      如果您知道它将是数字(这意味着它永远不会将整数转换为字符串,例如 "ten""100",您可以使用 is_int()

      $entityElementCount = (-($highScore-$totalKeywordCount))/0.29;
      $entityWholeNumber = is_int($entityElementCount);
      
      echo ($entityWholeNumber) ? "Whole Number!" : "Not a whole number!";
      

      【讨论】:

      • 很好,但是这里的三元运算符是多余的。只需$entityWholeNumber = is_int($entityElementCount) 就足够了
      • 您的两个代码示例完全相同,第二个只是将is_int 调用的结果存储在一个变量中(我可能会以一种相当麻烦的方式添加)。此外,这会检查 var 是否为 int,而不是检查包含的值是否为整数。
      • 整数总是整数。如果他想知道它是整数还是非整数,那意味着它是整数或浮点数。代码示例应该做同样的事情。
      • 根据定义,整数类似于整数,但它们可以包含负号。整数没有负号。
      • @ghostdog74 - 整数可以是负数。您正在考虑自然数,它也不能包含 0。用户并没有问它是否是完整的和实数,只是完整的。整数和整数是一回事。更不用说提供的任何舍入技术也不会检查数字是否小于 0。
      【解决方案7】:

      我测试了所有提出的解决方案,其中提到了许多有问题的值,它们至少在一个测试用例中都失败了。开始检查$value 是否是一个数字,使用is_numeric($value) 可以减少许多解决方案的失败次数,但不会将任何解决方案变成终极解决方案:

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

      我认为像@Aistina 和@Notinlist 提出的解决方案是最好的,因为它们使用错误阈值来确定一个值是否为整数。需要注意的是,对于表达式 (-(4.42-5))/0.29,它们按预期工作,而在该测试用例中,所有其他表达式都失败了。

      我决定使用@Notinlist 的解决方案,因为它的可读性:

      function is_whole_number($value) {
          return (is_numeric($value) && (round($value, 3) == round($value)));
      }
      

      我需要测试值是整数、货币还是百分比,我认为 2 位数的精度就足够了,所以 @Notinlist 的解决方案符合我的需求。

      运行此测试:

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

      产生以下输出:

      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
      

      【讨论】:

      • 你算法的主要问题是0.999999997不是一个整数。
      • 正如我所说,我需要测试值是整数、货币还是百分比,所以我采用了 2 位精度。如果您需要调整精度,只需更改round($value, 3)。使用round($value, 9) 产生float(0.999999997) is a whole number? no
      • 所以请记住,所有这些都受php.ini 中的precision 设置的约束。如果您将其设置为 8 或更少,则 float(0.999999997) 是一个整数。但是,如果您将其设置为 20 ,则为 float(0.999999997) =&gt; 0.99999999699999997382。默认值为 14 我认为这样仍然会产生差异。您的算法非常适用于统计数据,这是它的目的,但不是货币或输入验证。
      【解决方案8】:
      if(floor($number) == $number)
      

      不是一个稳定的算法。当数值为 1.0 时,数值可以是 0.9999999。如果你在它上面应用 floor() 它将是 0 不等于 0.9999999。

      你必须猜测一个精度半径,例如 3 位数

      if(round($number,3) == round($number))
      

      【讨论】:

        【解决方案9】:
            $num = 2.0000000000001;
            if( $num == floor( $num  ) ){
                echo('whole');
            }else{
                echo('fraction');
            }
        

        前:

        2.0000000000001 |分数

        2.1 |分数

        2.00 |整体

        2 |整体

        【讨论】:

          【解决方案10】:
          (string)floor($pecahformat[3])!=(string)$pecahformat[3]
          

          【讨论】:

          • $pecahformat=123.5$pecahformat="123.5" 上都失败,它认为123.5 是一个整数。
          【解决方案11】:
          floor($entityElementCount) == $entityElementCount
          

          如果这是一个整数,这将是正确的

          【讨论】:

          • 不适用于所有花车。 php -r "$n = (-(4.42-5))/0.29;var_dump($n, floor($n) == $n);"浮动(2)布尔(假)
          • $entityElementCount="123foobar"; 上失败(它认为 123foobar 是一个整数。)
          【解决方案12】:

          这并不是试图回答这个问题。他们已经有很多答案了。如果您像问题所暗示的那样进行统计,我怀疑@antonio-vinicius-menezes-medei 答案最适合您。但是我需要这个答案来验证输入。我发现这个检查更可靠地验证输入字符串是一个整数:

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

          “is_numeric”只是纠正 preg_match 中“true”转换为“1”的情况。

          所以玩@antonio-vinicius-menezes-medei 的答案。我写了一个脚本来测试这个。注意ini_set('precision', 20)。 preg_match 会将参数转换为字符串。如果您的精度设置为低于浮点值的长度,它们将简单地以给定的精度四舍五入。与@antonio-vinicius-menezes-medei 回答类似,此精度设置将强制使用类似的估计长度。

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

          产生这个输出:

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

          【讨论】:

            【解决方案13】:

            @Tyler Carter 解决方案的改进版本,它比原来更好地处理边缘情况:

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

            (Tyler 的代码无法识别字符串“123foobar”不是整数。这个改进的版本不会犯这个错误。感谢 cmets 中的 @Shafizadeh 发现错误。这也是 php7 strict_types=1 -兼容)

            【讨论】:

              【解决方案14】:

              似乎一种简单的方法是使用模数 (%) 来确定一个值是否为整数。

              x = y % 1  
              

              如果 y 不是整数,则结果不是零 (0)。那么测试将是:

              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. 
              

              当然,这会将负数视为一个整数,然后只需将 ABS() 包裹在 y 周围以始终测试正数。

              【讨论】:

              • 这其实不是真的。出于某种原因,1.4 % 1 返回 0。我假设 php 在进行模数之前强制转换为 int。但是 fmod(1.4, 1) 确实返回了预期的 0.4
              • 你可以这样做 (x * 5.0) % 5.0) 但前提是 x 中的小数至少是 0.1,因为 php 会进行四舍五入。
              【解决方案15】:

              我总是使用类型转换来检查变量是否包含整数,当您不知道值的来源或类型时很方便。

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

              在你的特殊情况下,我会使用is_int()

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

              【讨论】:

                【解决方案16】:

                仅适用于正整数的简单解决方案。这可能并不适用于所有情况。

                $string = '0x539';
                $ceil = ceil($string);
                
                if($ceil < 1){
                  $ceil = FALSE; // or whatever you want i.e 0 or 1
                }
                
                echo $ceil; // 1337
                

                如果需要,您可以使用 floor() 代替 ceil()。

                【讨论】:

                  【解决方案17】:
                  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 (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
                  }
                  

                  这将正确检查您的数字,而无需对其进行四舍五入、将其转换为 int(在十进制数字的情况下将丢失小数部分)或进行任何数学运算。但是,如果您想将 1.00 视为一个整数,那就另当别论了。

                  【讨论】:

                  • 对不起,我的 PHP,解释器,php -r "var_dump(is_int(log(8, 2) + 0));" => 布尔(假)
                  • 对我来说也是错误的,因为 log(8, 2) = float/double,而不是 int。我认为你不明白这是做什么的。 +0 仅用于将数字字符串转换为数字。
                  • 最初的问题是关于花车的。 @jurchiks对不起,我只是指出这个答案不起作用。
                  • 这不是我的代码的问题。如果我的函数接收到一个浮点数,它显然会说它不是一个 int。阅读我回答的最后一句话。
                  • 我出现在此页面的原因是确定浮动是否像 OP 的问题一样完整。答案似乎不合适或错误。
                  【解决方案18】:

                  我知道这是一篇超级旧的帖子,但这是一个简单的函数,它将返回一个有效的整数并将其转换为一个 int。如果失败则返回 false。

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

                  用法:

                  $a = 43;
                  $b = 4.3;
                  $c = 'four_three';
                  
                  isWholeNumber($a) // 43
                  isWholeNumber($b) // false
                  isWholeNumber($c) // false
                  

                  【讨论】:

                    【解决方案19】:

                    只是为了与本地化字符串/数字分享我的解决方案,这个组合对我来说就像一个魅力。

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

                    【讨论】:

                      【解决方案20】:
                      $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`
                      

                      【讨论】:

                        【解决方案21】:

                        我想出的另一种 hacky 方式是 ceil($value) === floor($value)。如果一个数字是一个整数,这应该总是正确的,即使将 10 与 10.000 进行比较,甚至可以使用字符串中的数字,例如ceil("10.0") === floor(10)

                        【讨论】:

                          猜你喜欢
                          • 2013-10-14
                          • 2011-09-18
                          • 2014-01-25
                          • 1970-01-01
                          • 2015-02-25
                          • 2011-03-30
                          • 1970-01-01
                          • 1970-01-01
                          • 1970-01-01
                          相关资源
                          最近更新 更多