【问题标题】:How to make number_format() not to round numbers up如何使 number_format() 不四舍五入
【发布时间】:2010-09-30 17:19:44
【问题描述】:

我有这个号码:

$double = '21.188624';

使用number_format($double, 2, ',', ' ')后我得到:

21,19

但我想要的是:

21,18

任何想法我怎样才能使这项工作?

谢谢。

【问题讨论】:

  • 你可以简单地减去 5 * 10 ^ - ( 1 + 小数位)。所以number_format($double - 0.005, 2, ',', ' ')

标签: php


【解决方案1】:

number_format 总是会这样做,你唯一的解决办法是给它一些不同的东西:

$number = intval(($number*100))/100;

或者:

$number = floor(($number*100))/100;

【讨论】:

  • 用这个数字试试这个:0.29,它失败了!
  • 这样做:$finalCommishParts = explode('.',$commission); $commisshSuffix = (isset($finalCommishParts[1])?substr($finalCommishParts[1],0,2):'00'); $finalCommish = $finalCommishParts[0].'.'.$commisshSuffix;
  • @AsafMaoz:注意小数点分隔符与语言环境的差异。
  • @Arsham:那是因为 0.29 不作为浮点数存在:printf('%.20f',0.29) 向您显示:0.28999999999999998002,因此,它正确地强制向下舍入。
  • @AsafMaoz:顺便说一句,您也可以使用 str_pad($string, 2,'0',STR_PAD_RIGHT) 代替 substring 方法。
【解决方案2】:

我知道这是一个老问题,但它仍然是实际的:)。

这个功能怎么样?

function numberFormatPrecision($number, $precision = 2, $separator = '.')
{
    $numberParts = explode($separator, $number);
    $response = $numberParts[0];
    if (count($numberParts)>1 && $precision > 0) {
        $response .= $separator;
        $response .= substr($numberParts[1], 0, $precision);
    }
    return $response;
}

用法:

// numbers test
numberFormatPrecision(19, 2, '.'); // expected 19 return 19
numberFormatPrecision(19.1, 2, '.'); //expected 19.1 return 19.1
numberFormatPrecision(19.123456, 2, '.'); //expected 19.12 return 19.12
numberFormatPrecision(19.123456, 0, '.'); //expected 19 return 19

// negative numbers test
numberFormatPrecision(-19, 2, '.'); // expected -19 return -19
numberFormatPrecision(-19.1, 2, '.'); //expected -19.1 return -19.1
numberFormatPrecision(-19.123456, 2, '.'); //expected -19.12 return -19.12
numberFormatPrecision(-19.123456, 0, '.'); //expected -19 return -19

// precision test
numberFormatPrecision(-19.123456, 4, '.'); //expected -19.1234 return -19.1234

// separator test
numberFormatPrecision('-19,123456', 3, ','); //expected -19,123 return -19,123  -- comma separator

【讨论】:

    【解决方案3】:

    函数(仅精度):

    function numberPrecision($number, $decimals = 0)
    {
        $negation = ($number < 0) ? (-1) : 1;
        $coefficient = 10 ** $decimals;
        return $negation * floor((string)(abs($number) * $coefficient)) / $coefficient;
    }
    

    例子:

    numberPrecision(2557.9999, 2);     // returns 2557.99
    numberPrecision(2557.9999, 10);    // returns 2557.9999
    numberPrecision(2557.9999, 0);     // returns 2557
    numberPrecision(2557.9999, -2);    // returns 2500
    numberPrecision(2557.9999, -10);   // returns 0
    numberPrecision(-2557.9999, 2);    // returns -2557.99
    numberPrecision(-2557.9999, 10);   // returns -2557.9999
    numberPrecision(-2557.9999, 0);    // returns -2557
    numberPrecision(-2557.9999, -2);   // returns -2500
    numberPrecision(-2557.9999, -10);  // returns 0
    

    功能(全功能):

    function numberFormat($number, $decimals = 0, $decPoint = '.' , $thousandsSep = ',')
    {
        $negation = ($number < 0) ? (-1) : 1;
        $coefficient = 10 ** $decimals;
        $number = $negation * floor((string)(abs($number) * $coefficient)) / $coefficient;
        return number_format($number, $decimals, $decPoint, $thousandsSep);
    }
    

    例子:

    numberFormat(2557.9999, 2, ',', ' ');     // returns 2 557,99
    numberFormat(2557.9999, 10, ',', ' ');    // returns 2 557,9999000000
    numberFormat(2557.9999, 0, ',', ' ');     // returns 2 557
    numberFormat(2557.9999, -2, ',', ' ');    // returns 2 500
    numberFormat(2557.9999, -10, ',', ' ');   // returns 0
    numberFormat(-2557.9999, 2, ',', ' ');    // returns -2 557,99
    numberFormat(-2557.9999, 10, ',', ' ');   // returns -2 557,9999000000
    numberFormat(-2557.9999, 0, ',', ' ');    // returns -2 557
    numberFormat(-2557.9999, -2, ',', ' ');   // returns -2 500
    numberFormat(-2557.9999, -10, ',', ' ');  // returns 0
    

    【讨论】:

    • 天啊。谢谢。它实际上是我搜​​索的。
    • 太好了,谢谢
    【解决方案4】:
    floor($double*100)/100
    

    【讨论】:

      【解决方案5】:

      我使用这个功能:

      function cutNum($num, $precision = 2) {
          return floor($num) . substr(str_replace(floor($num), '', $num), 0, $precision + 1);
      }
      

      用法示例:

      cutNum(5)          //returns 5 
      cutNum(5.6789)     //returns 5.67 (default precision is two decimals)
      cutNum(5.6789, 3)  //returns 5.678
      cutNum(5.6789, 10) //returns 5.6789
      cutNum(5.6789, 0)  //returns 5. (!don't use with zero as second argument: use floor instead!)
      

      解释:这里你有 same 函数,只是更详细以帮助理解它的行为:

      function cutNum($num, $precision = 2) {
          $integerPart = floor($num);
          $decimalPart = str_replace($integerPart, '', $num);
          $trimmedDecimal = substr($decimalPart, 0, $precision + 1);
          return $integerPart . $trimmedDecimal;
      }
      

      【讨论】:

      • 你节省了我的时间谢谢
      • test cutNum(510.9) // 返回 510.89
      • 感谢@ustmaestro,这要归功于 Php floating conversion issue。我已经用字符串替换函数替换了浮动计算,作为这种情况的解决方法。
      • 你的函数不正确。当它应该返回 99.99 时,99.997092 将返回 99.70。这是正确的功能。 pastebin.com/6i9X536G
      • 一开始我很喜欢它,直到我使用 gettype() 发现它是一个字符串而不是真正的双精度
      【解决方案6】:

      使用 PHP 原生函数bcdiv

      function numberFormat($number, $decimals = 2, $sep = ".", $k = ","){
          $number = bcdiv($number, 1, $decimals); // Truncate decimals without rounding
          return number_format($number, $decimals, $sep, $k); // Format the number
      }
      

      更多详情请见this answer

      【讨论】:

      • 这个解决方案非常好,但是您需要将字符串提供给 bcdiv 否则如果您尝试对小数字进行 numberFormat 它将打印 0.00000(我对其进行了测试,但它不适用于 0.00001)。解决方案:$number = bcdiv(number_format($number, 30, '.', ''), '1', $decimals);
      【解决方案7】:
       **Number without round**        
      
         $double = '21.188624';
         echo intval($double).'.'.substr(end(explode('.',$double)),0,2);
      
      **Output** 21.18
      

      【讨论】:

        【解决方案8】:

        如果您不关心小数点后面的内容,可以将float 转换为int 以避免四舍五入:

        $float = 2.8;
        echo (int) $float; // outputs '2'
        

        【讨论】:

          【解决方案9】:
          $double = '21.188624';
          
          $teX = explode('.', $double);
          
          if(isset($teX[1])){
              $de = substr($teX[1], 0, 2);
              $final = $teX[0].'.'.$de;
              $final = (float) $final;
          }else{
              $final = $double;   
          }
          

          决赛时间是 21.18

          【讨论】:

            【解决方案10】:
            public function numberFormatPrecision( $number, $separator = '.', $format = 2 ){
            
                $response = '';
                $brokenNumber = explode( $separator, $number );
                $response = $brokenNumber[0] . $separator;
                $brokenBackNumber = str_split($brokenNumber[1]);
            
                if( $format < count($brokenBackNumber) ){
            
                    for( $i = 1; $i <= $format; $i++ )
                        $response .= $brokenBackNumber[$i];
                }
            
                return $response;
            }
            

            【讨论】:

            • 你不能有 for( $i = 1;... 因为 $brokenBackNumber[$i] 会错过第一个字符 - 因为 $brokenBackNumber 是从零开始的。你还应该有一个 'else{ }' 部分用于您的 if 语句。但我喜欢您的想法。
            【解决方案11】:
            $finalCommishParts = explode('.',$commission);
            $commisshSuffix = (isset($finalCommishParts[1])?substr($finalCommishParts[1],0,2):'00');
            $finalCommish = $finalCommishParts[0].'.'.$commisshSuffix;
            

            【讨论】:

            • 请添加说明文字。我在这个答案中没有看到number_format(...),所以我无法回答“如何使 number_format() 不向上舍入”的问题
            • 这个 sn-p 做了 number_format 做的事情,但没有四舍五入。如上所述,检查您当地的小数点分隔符。
            【解决方案12】:

            爆炸(构建数组)更快的方法是使用这样的字符串命令:

            $number = ABC.EDFG;
            $precision = substr($number, strpos($number, '.'), 3); // 3 because . plus 2 precision  
            $new_number = substr($number, 0, strpos($number, '.')).$precision;
            

            在这种情况下,结果是 ABC.ED,因为 2 精度 如果您想要更高的精度,只需将 3 更改为 4 或 X 以具有 X-1 精度

            干杯

            【讨论】:

              【解决方案13】:

              Javascript 版本

              function numberFormat($number, $decimals = 0, $decPoint = '.' , $thousandsSep = ',')
              {
                  return number_format((Math.floor($number * 100) / 100).toFixed($decimals), $decimals, $decPoint, $thousandsSep );
              }
               // https://locutus.io/php/strings/number_format/
              function number_format(number, decimals, decPoint, thousandsSep) {
                  if(decimals === 'undefined') decimals = 2;
              
                  number = (number + '').replace(/[^0-9+\-Ee.]/g, '')
                const n = !isFinite(+number) ? 0 : +number
                const prec = !isFinite(+decimals) ? 0 : Math.abs(decimals)
                const sep = (typeof thousandsSep === 'undefined') ? ',' : thousandsSep
                const dec = (typeof decPoint === 'undefined') ? '.' : decPoint
                let s = ''
                const toFixedFix = function (n, prec) {
                  if (('' + n).indexOf('e') === -1) {
                    return +(Math.round(n + 'e+' + prec) + 'e-' + prec)
                  } else {
                    const arr = ('' + n).split('e')
                    let sig = ''
                    if (+arr[1] + prec > 0) {
                      sig = '+'
                    }
                    return (+(Math.round(+arr[0] + 'e' + sig + (+arr[1] + prec)) + 'e-' + prec)).toFixed(prec)
                  }
                }
                // @todo: for IE parseFloat(0.55).toFixed(0) = 0;
                s = (prec ? toFixedFix(n, prec).toString() : '' + Math.round(n)).split('.')
                if (s[0].length > 3) {
                  s[0] = s[0].replace(/\B(?=(?:\d{3})+(?!\d))/g, sep)
                }
                if ((s[1] || '').length < prec) {
                  s[1] = s[1] || ''
                  s[1] += new Array(prec - s[1].length + 1).join('0')
                }
                return s.join(dec)
              }
              

              【讨论】:

                【解决方案14】:

                如果您需要 2 个固定小数位,您可以试试这个!

                @Dima 的解决方案对我有用,但它会将“19.90”打印为“19.9”,因此我进行了一些更改,如下所示:

                <?php 
                function numberPrecision($number, $decimals = 0)
                    {
                        $negation = ($number < 0) ? (-1) : 1;
                        $coefficient = 10 ** $decimals;
                        $result = $negation * floor((string)(abs($number) * $coefficient)) / $coefficient;
                        $arr = explode(".", $result);
                        $num = $arr[0];
                        if(empty($arr[1]))
                            $num .= ".00";
                        else if(strlen($arr[1]) == 1)
                            $num .= "." . $arr[1] . "0";
                        else
                            $num .= ".". $arr[1];
                        return $num;
                    }
                    echo numberPrecision(19.90,2); // 19.90
                

                所以,我所做的是,我只是将结果分解为具有爆炸功能的两部分。并将结果转换为带有连接的字符串!

                【讨论】:

                  【解决方案15】:

                  使用此功能:

                  function number_format_unlimited_precision($number,$decimal = '.')
                  {
                     $broken_number = explode($decimal,$number);
                     return number_format($broken_number[0]).$decimal.$broken_number[1]);
                  }
                  

                  【讨论】:

                  • 你有一个额外的 ) $broken_number[1]);
                  • 这什么也不做:只返回与传递相同的输入数字(也存在括号拼写错误)。
                  • 我知道这是一个旧的回应,这不是一个很好的答案,但让我们清楚的是有一个编辑,如果你看看历史,额外的括号是由这个 Linus 老兄添加的,而不是由原始回答者提供。
                  【解决方案16】:

                  如果您的 float 值较小,您可以通过这种方式使用 number_format 函数。

                  $number = 21.23;
                  
                  echo number_format($number, 2, '.', ',') ); // 21.23
                  

                  如果你有长十进制数,那么它也会以这种方式格式化数字

                  $number = 201541.23;
                  
                  echo number_format($number, 2, '.', ',') ); // 201,541.23
                  

                  【讨论】:

                  • 这完全不是问题的答案
                  猜你喜欢
                  • 2011-08-30
                  • 2023-01-12
                  • 1970-01-01
                  • 2022-11-21
                  • 1970-01-01
                  • 2012-08-04
                  • 2023-03-26
                  • 1970-01-01
                  • 1970-01-01
                  相关资源
                  最近更新 更多