【问题标题】:Format number to always show 2 decimal places将数字格式化为始终显示 2 位小数
【发布时间】:2011-09-02 07:20:07
【问题描述】:

我想将我的数字格式化为始终显示 2 位小数,并在适用的情况下四舍五入。

例子:

number     display
------     -------
1          1.00
1.341      1.34
1.345      1.35

我一直在用这个:

parseFloat(num).toFixed(2);

但它将1 显示为1,而不是1.00

【问题讨论】:

标签: javascript floating-point number-formatting


【解决方案1】:
(Math.round(num * 100) / 100).toFixed(2);

现场演示

var num1 = "1";
document.getElementById('num1').innerHTML = (Math.round(num1 * 100) / 100).toFixed(2);

var num2 = "1.341";
document.getElementById('num2').innerHTML = (Math.round(num2 * 100) / 100).toFixed(2);

var num3 = "1.345";
document.getElementById('num3').innerHTML = (Math.round(num3 * 100) / 100).toFixed(2);
span {
    border: 1px solid #000;
    margin: 5px;
    padding: 5px;
}
<span id="num1"></span>
<span id="num2"></span>
<span id="num3"></span>

请注意,它将四舍五入到小数点后 2 位,因此输入 1.346 将返回 1.35

【讨论】:

  • @Kooilnc:OP 希望1 显示为1.001.341 显示为1.34
  • 不需要使用 round(),因为 toFixed() 会舍入它。
  • toFixed() 会对其进行舍入,但不要忘记它返回的是一个字符串……所以这种方法实际上只对显示有用。如果要对舍入值执行进一步的数学计算,请不要使用 toFixed()。
  • 根据 MDN,由于舍入误差,Math.round 并不总是能给出准确的结果。我用 1.005 对此进行了测试,它应该四舍五入到 1.01,但它给出了 1.00。使用我的答案以获得一致的准确性:stackoverflow.com/a/34796988/3549440.
  • 整个答案可以简化为(+num).toFixed(2)。它甚至保留了原版中的舍入错误,请参阅Nate's answer
【解决方案2】:
Number(1).toFixed(2);         // 1.00
Number(1.341).toFixed(2);     // 1.34
Number(1.345).toFixed(2);     // 1.34 NOTE: See andy's comment below.
Number(1.3450001).toFixed(2); // 1.35

document.getElementById('line1').innerHTML = Number(1).toFixed(2);
document.getElementById('line2').innerHTML = Number(1.341).toFixed(2);
document.getElementById('line3').innerHTML = Number(1.345).toFixed(2);
document.getElementById('line4').innerHTML = Number(1.3450001).toFixed(2);
<span id="line1"></span>
<br/>
<span id="line2"></span>
<br/>
<span id="line3"></span>
<br/>
<span id="line4"></span>

【讨论】:

  • @Andre,Chrome 29.0.1547.57 给我1.34 表达Number(1.345).toFixed(2)
  • toFixed does 进行舍入,您几乎可以在每个测试编号上看到。
  • 在完成之前不小心提交了最后一条评论。1.345 是一个不能精确存储为浮点数的数字的例子,所以我认为它没有像你一样四舍五入的原因期望,是它实际上存储为一个略小于 1.345 的数字,并且向下舍入。如果您使用(1.34500001).toFixed(2) 进行测试,那么您会看到它正确地四舍五入到1.35
  • 很晚了,但为了阐明“5”的四舍五入,它总是四舍五入到最接近的偶数。 1.345 将四舍五入为 1.34,但 1.335 也是如此。一半时间 5 上升,一半时间 5 下降。
  • @Bardicer,使用 toFixed(2) 将 1.335 舍入到 1.33
【解决方案3】:

如果value = 1.005This answer 将失败。

作为更好的解决方案,可以通过使用指数表示法表示的数字来避免舍入问题:

Number(Math.round(1.005+'e2')+'e-2'); // 1.01

@Kon 和原作者建议的更简洁的代码:

Number(Math.round(parseFloat(value + 'e' + decimalPlaces)) + 'e-' + decimalPlaces)

您可以在末尾添加toFixed() 以保留小数点,例如:1.00,但请注意它将作为字符串返回。

Number(Math.round(parseFloat(value + 'e' + decimalPlaces)) + 'e-' + decimalPlaces).toFixed(decimalPlaces)

信用:Rounding Decimals in JavaScript

【讨论】:

  • 令人惊讶的是,这里的其他人都没有看到toFixed 有这个舍入问题。你的答案应该是被接受的。
  • 刚刚测试看看是否仍然如此。您对 Chrome 版本 59.0.3071.115 仍然正确 您的解决方案将四舍五入为 1.005 (1.01) 并向下舍入为 1.00499999 (1.00)
  • jsfiddle.net/Artistan/qq895bnp/28 toFixed 有时会起作用,但非常不一致。 :)
  • parseFloat 中的环绕数字是它的返回字符串
  • 这是一个可靠的答案。我能想到的一些改进:(1)VS Code(TypeScript 文件)不喜欢 Math.round() 传递字符串。 (2) 使小数位数动态化(未硬编码为 2)。 (3) toFixed() 似乎没有必要。所以我想出的是Number(Math.round(parseFloat(value + 'e' + decimalPlaces)) + 'e-' + decimalPlaces)
【解决方案4】:

对于现代浏览器,请使用toLocaleString:

var num = 1.345;
num.toLocaleString(undefined, { maximumFractionDigits: 2, minimumFractionDigits: 2 });

指定一个语言环境标记作为第一个参数来控制decimal separator。对于点,例如使用英语美国语言环境:

num.toLocaleString("en-US", { maximumFractionDigits: 2, minimumFractionDigits: 2 });

给出:

1.35

欧洲的大多数国家/地区使用逗号作为小数分隔符,因此如果您使用瑞典/瑞典语言环境:

num.toLocaleString("sv-SE", { maximumFractionDigits: 2, minimumFractionDigits: 2 });

它会给出:

1,35

【讨论】:

    【解决方案5】:
    var num = new Number(14.12);
    console.log(num.toPrecision(2));//outputs 14
    console.log(num.toPrecision(3));//outputs 14.1
    console.log(num.toPrecision(4));//outputs 14.12
    console.log(num.toPrecision(5));//outputs 14.120
    

    【讨论】:

    • 这会产生意想不到的结果,如果你的数字可以是 1.4、23.654 和 0,你会采用什么精度?
    • 请注意,OP 要求 “在适用的情况下进行四舍五入”toPrecision 仅将数字格式化为特定的小数位数,只是省略了多余的位置,但不四舍五入。当然,这也可能非常有用,但了解其中的区别很重要。
    • 根据 Mozilla 的说法,实际上 toPrecision 确实是圆的。测试:(20.55).toPrecision(3) "20.6"
    • 如果你想strip trailing zeros,在使用toFixed后将其转换为数字或浮点数:const formattedVal = Number(val.toFixed(2)); 不要使用toPrecision,因为它在使用精度参数。
    【解决方案6】:

    为了最精确的舍入,创建这个函数:

    function round(value, decimals) {
        return Number(Math.round(value +'e'+ decimals) +'e-'+ decimals).toFixed(decimals);
    }
    

    并用它来四舍五入到小数点后两位:

    console.log("seeked to " + round(1.005, 2));
    > 1.01
    

    感谢Razuthis 文章和MDN's Math.round reference

    【讨论】:

    【解决方案7】:

    我建议你使用

    new Intl.NumberFormat('de-DE', { minimumFractionDigits: 2, maximumFractionDigits: 2 }).format(num)
    

    这样您也将拥有您指定的国家/地区的本地格式,而且它会保证显示精确的 2 位小数(无论 num 是 1 还是 1.12345,它都会分别显示 1.00 和 1.12)

    在此示例中,我使用了德语本地化,因为我希望我的数字以千位分隔符显示,所以这将是一些输出:

    1 => 1,00
    1.12 => 1,12
    1.1234 => 1,12
    1234 => 1.234,00
    1234.1234 => 1.234,12
    

    【讨论】:

    • 被低估的答案。这种方法可以格式化所有你想要的格式,从千位到小数位
    • Ich küsse deine Augen.
    • 很好的答案。谢谢你。作为旁注:这个英文版本使用:'en-US'而不是'de-DE'
    • @Dave 正如我解释的那样,我故意使用德语作为非典型格式来表达观点。可以使用任何想要的本地化,有数百个。另一个英文例子是 'en-GB'
    【解决方案8】:

    最简单的答案:

    var num = 1.2353453;
    num.toFixed(2); // 1.24
    

    示例:http://jsfiddle.net/E2XU7/

    【讨论】:

    • 好吧,toFixed 已经在 stackoverflow.com/a/13292833/218196 中提出。您的问题提供了哪些额外信息?
    • 那个答案不包括圆形功能,我的答案包括。
    • 呃?这是完全相同的答案。在号码上拨打toFixed
    • 正确,功能相同,但该答案的结果具有误导性,我只是通过表达圆形功能来纠正它。
    • 问题说明:“......在适用的情况下四舍五入”。您的答案不涉及四舍五入。
    【解决方案9】:

    四舍五入到 N 位的更通用的解决方案

    function roundN(num,n){
      return parseFloat(Math.round(num * Math.pow(10, n)) /Math.pow(10,n)).toFixed(n);
    }
    
    
    console.log(roundN(1,2))
    console.log(roundN(1.34,2))
    console.log(roundN(1.35,2))
    console.log(roundN(1.344,2))
    console.log(roundN(1.345,2))
    console.log(roundN(1.344,3))
    console.log(roundN(1.345,3))
    console.log(roundN(1.3444,3))
    console.log(roundN(1.3455,3))
    
    Output
    
    1.00
    1.34
    1.35
    1.34
    1.35
    1.344
    1.345
    1.344
    1.346
    

    【讨论】:

    • 此算法失败,某些数字接近 0,roundN(-3.4028230607370965e+38,2) 返回 "-3.4028230607370965e+38" 而不是预期的 0.00
    • 有趣的@Ferrybig 我会测试你提到的数字并想出一个解决方法,感谢测试
    • 请注意,前面提到的数字不应该显示为零,而是一个巨大的数字,这只是我的大脑中的一个错误。但它仍然不起作用,因为它仍然不显示 2 位小数
    【解决方案10】:
    var number = 123456.789;
    
    
    console.log(new Intl.NumberFormat('en-IN', { maximumFractionDigits: 2 }).format(number));
    

    https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/NumberFormat

    【讨论】:

      【解决方案11】:

      如果您已经在使用 jQuery,可以考虑使用 jQuery Number Format 插件。

      插件可以将格式化的数字返回为字符串,可以设置小数,千位分隔符,可以选择显示的小数位数。

      $.number( 123, 2 ); // Returns '123.00'
      

      你也可以得到jQuery Number Format from GitHub

      【讨论】:

      • 使用插件“只是为了有固定长度的小数部分”是矫枉过正的。
      • @Lashae,当然,如果这就是你想要做的。我发布了这个以防 OP 或其他任何人想要插件提供的额外功能。
      • 如果问题的发布者当然添加了 jQuery 标签 ;)
      【解决方案12】:

      这是你的意思吗?

      [edit 20200530] 答案@razu provided 是最好的恕我直言。所以这里有一个稍微重构的版本。

      sn-p 代码仍然不会为 showAsFloat(2.3346) 之类的东西返回正确的值(结果为 2.33,但应该是 2.34)。所以,see also

      const showAsFloat = (input, decimals = 2, asString = false) => {
        if (input === null || input.constructor === Boolean || isNaN(+input)) {
          return input;
        }
        const converted = +( `${Math.round( parseFloat( `${input}e${decimals}` )  )}e-${decimals}` );
        return asString ? converted.toFixed(decimals) : converted
      };
      
      document.querySelector('#result').textContent = [
        'command                      | result',
        '-----------------------------------------------',
        'showAsFloat(1);              | ' + showAsFloat(1),
        'showAsFloat(1.314);          | ' + showAsFloat(1.314),
        'showAsFloat(\'notanumber\')    | ' + showAsFloat('notanumber'),
        'showAsFloat(\'23.44567\', 3)   | ' + showAsFloat('23.44567', 3),
        'showAsFloat(2456198, 5, true)| ' + showAsFloat('24568', 5, true),
        'showAsFloat(2456198, 5)      | ' + showAsFloat('24568', 5),
        'showAsFloat(0, 2, true);     | ' + showAsFloat(0, 2, true),
        'showAsFloat(1.345);          | ' + showAsFloat(1.345),
        'showAsFloat(0.005);          | ' + showAsFloat(0.005),
        'showAsFloat(null);           | ' + showAsFloat(null),
      
      ].join('\n');
      &lt;pre id="result"&gt;&lt;/pre&gt;

      【讨论】:

      • 请注意,此解决方案在某些情况下将无法正确舍入:1.005 得出1.00,而1.345 得出1.34
      • 这就是为什么@razu 的答案应该被接受的原因......
      【解决方案13】:

      你在找地板吗?

      var num = 1.42482;
      var num2 = 1;
      var fnum = Math.floor(num).toFixed(2);
      var fnum2 = Math.floor(num2).toFixed(2);
      alert(fnum + " and " + fnum2); //both values will be 1.00
      

      【讨论】:

      • 我认为他不想四舍五入到最接近的整数。
      • 是的,从描述中我不确定,但我只是把它扔在那里以防万一
      【解决方案14】:

      将数字转换为字符串,只保留两位小数:

      var num = 5.56789;
      var n = num.toFixed(2);
      

      n 的结果将是:

      5.57
      

      【讨论】:

        【解决方案15】:

        遇到这个最长的线程,下面是我的解决方案:

        parseFloat(Math.round((parseFloat(num * 100)).toFixed(2)) / 100 ).toFixed(2)
        

        如果有人可以戳洞,请告诉我

        【讨论】:

          【解决方案16】:
          function currencyFormat (num) {
              return "$" + num.toFixed(2).replace(/(\d)(?=(\d{3})+(?!\d))/g, "$1,")
          }
          
          console.info(currencyFormat(2665));   // $2,665.00
          console.info(currencyFormat(102665)); // $102,665.00
          

          【讨论】:

            【解决方案17】:

            你没有给我们完整的画面。

            javascript:alert(parseFloat(1).toFixed(2)) 在我将其粘贴到地址栏中时在我的浏览器中显示 1.00。 但是,如果您事后对其进行操作,它将恢复。

            alert(parseFloat(1).toFixed(2))
            
            var num = 2
            document.getElementById('spanId').innerHTML = (parseFloat(num).toFixed(2) - 1)
            &lt;span id="spanId"&gt;&lt;/span&gt;
            shows 1 and not 1.00
            

            【讨论】:

            • 适用于 FF 50、Chrome 49 和 IE 8
            【解决方案18】:

            这里还有一个可以格式化为任意小数位的通用函数:

            function numberFormat(val, decimalPlaces) {
            
                var multiplier = Math.pow(10, decimalPlaces);
                return (Math.round(val * multiplier) / multiplier).toFixed(decimalPlaces);
            }
            

            【讨论】:

              【解决方案19】:

              如果需要特定格式,您应该编写自己的例程或使用库函数来满足您的需要。基本的 ECMAScript 功能通常不足以显示格式化数字。

              关于舍入和格式的详尽解释在这里:http://www.merlyn.demon.co.uk/js-round.htm#RiJ

              作为一般规则,舍入和格式化应仅作为输出前的最后一步执行。提前这样做可能会引入意外的大错误并破坏格式。

              【讨论】:

              • 有时我会因为自己的选择而摇头,以至于最近如此深入地参与到整个 JS/Ecma 平台中。 :( “在需要特定格式的情况下,您应该编写自己的例程或使用库函数来满足您的需要。基本的 ECMAScript 功能通常不足以显示格式化的数字。”多么愚蠢的声明 - 不是你做的,但因为这个事实存在。只是伤心。开始吧,Javascript!:)
              【解决方案20】:

              这是另一种仅使用下限进行舍入的解决方案,意思是确保计算的金额不会大于原始金额(有时交易需要):

              Math.floor(num* 100 )/100;
              

              【讨论】:

                【解决方案21】:

                function number_format(string,decimals=2,decimal=',',thousands='.',pre='R$ ',pos=' Reais'){
                  var numbers = string.toString().match(/\d+/g).join([]);
                  numbers = numbers.padStart(decimals+1, "0");
                  var splitNumbers = numbers.split("").reverse();
                  var mask = '';
                  splitNumbers.forEach(function(d,i){
                    if (i == decimals) { mask = decimal + mask; }
                    if (i>(decimals+1) && ((i-2)%(decimals+1))==0) { mask = thousands + mask; }
                    mask = d + mask;
                  });
                  return pre + mask + pos;
                }
                var element = document.getElementById("format");
                var money= number_format("10987654321",2,',','.');
                element.innerHTML = money;
                #format{
                display:inline-block;
                padding:10px;
                border:1px solid #ddd;
                background:#f5f5f5;
                }
                &lt;div id='format'&gt;Test 123456789&lt;/div&gt;

                【讨论】:

                  【解决方案22】:

                  试试下面的代码:

                  function numberWithCommas(number) { 
                  
                     var newval = parseFloat(Math.round(number * 100) / 100).toFixed(2);
                  
                     return newval.toString().replace(/\B(?=(\d{3})+(?!\d))/g, ",");
                  }
                  

                  【讨论】:

                    【解决方案23】:
                    var quantity = 12;
                    
                    var import1 = 12.55;
                    
                    var total = quantity * import1;
                    
                    var answer = parseFloat(total).toFixed(2);
                    
                    document.write(answer);
                    

                    【讨论】:

                      【解决方案24】:

                      在调用 toFixed() 之前,我必须在 parseFloat() 和 Number() 转换之间做出决定。这是捕获用户输入后数字格式的示例。

                      HTML:

                      <input type="number" class="dec-number" min="0" step="0.01" />
                      

                      事件处理程序:

                      $('.dec-number').on('change', function () {
                           const value = $(this).val();
                           $(this).val(value.toFixed(2));
                      });
                      

                      以上代码会导致 TypeError 异常。请注意,虽然 html 输入类型是“数字”,但用户输入实际上是“字符串”数据类型。但是,toFixed() 函数只能在数字对象上调用。

                      我的最终代码如下所示:

                      $('.dec-number').on('change', function () {
                           const value = Number($(this).val());
                           $(this).val(value.toFixed(2));
                      });
                      

                      我喜欢使用 Number() 与 parseFloat() 进行强制转换的原因是因为我不必对空输入字符串或 NaN 值执行额外的验证。 Number() 函数会自动处理一个空字符串并将其转换为零。

                      【讨论】:

                        【解决方案25】:

                        var num1 = "0.1";
                        document.getElementById('num1').innerHTML = (Math.round(num1 * 100) / 100).toFixed(2);
                        
                        var num2 = "1.341";
                        document.getElementById('num2').innerHTML = (Math.round(num2 * 100) / 100).toFixed(2);
                        
                        var num3 = "1.345";
                        document.getElementById('num3').innerHTML = (Math.round(num3 * 100) / 100).toFixed(2);
                        span {
                            border: 1px solid #000;
                            margin: 5px;
                            padding: 5px;
                        }
                        <span id="num1"></span>
                        <span id="num2"></span>
                        <span id="num3"></span>

                        【讨论】:

                        • 这段代码足以满足你的要求parseFloat(num.toFixed(2))
                        【解决方案26】:

                        RegExp - 替代方法

                        在输入时你有字符串(因为你使用解析)所以我们可以通过只使用字符串操作和整数计算来得到结果

                        let toFix2 = (n) => n.replace(/(-?)(\d+)\.(\d\d)(\d+)/, (_,s,i,d,r)=> {
                          let k= (+r[0]>=5)+ +d - (r==5 && s=='-');
                          return s + (+i+(k>99)) + "." + ((k>99)?"00":(k>9?k:"0"+k));
                        })
                        
                        
                        // TESTs
                        
                        console.log(toFix2("1"));
                        console.log(toFix2("1.341"));
                        console.log(toFix2("1.345"));
                        console.log(toFix2("1.005"));

                        解释

                        • s 是符号,i 是整数部分,d 是点后的前两位,r 是其他数字(我们使用 r[0] 值来计算舍入)
                        • k 包含关于最后两位数字的信息(表示为整数)
                        • 如果r[0]&gt;=5,那么我们将1 添加到d - 但是如果我们有负数(s=='-')并且r 正好等于5,那么在这种情况下我们减去1(出于兼容性原因 - 以同样的方式 Math.round 适用于负数,例如 Math.round(-1.5)==-1
                        • 之后如果最后两位数k大于99,那么我们将整数部分加一i

                        【讨论】:

                          【解决方案27】:

                          我喜欢:

                          var num = 12.749;
                          parseFloat((Math.round(num * 100) / 100).toFixed(2)); // 123.75
                          

                          将数字四舍五入,保留 2 个小数点, 然后确保使用parseFloat() 解析它 返回数字,而不是字符串,除非您不在乎它是字符串还是数字。

                          【讨论】:

                          • 我猜如果目的是以 2 位小数精度显示,解析浮点数会搞砸。例如。 parseFloat("1.00") // 1
                          【解决方案28】:

                          precision方法扩展Math对象

                          Object.defineProperty(Math, 'precision',{
                             value: function (value,precision,type){
                                       var v = parseFloat(value),
                                           p = Math.max(precision,0)||0,
                                           t = type||'round';
                                        return (Math[t](v*Math.pow(10,p))/Math.pow(10,p)).toFixed(p);
                                    }
                              });
                          
                          console.log(
                              Math.precision(3.1,3), // round 3 digits 
                              Math.precision(0.12345,2,'ceil'), // ceil 2 digits
                              Math.precision(1.1) // integer part
                          )

                          【讨论】:

                            【解决方案29】:

                            您可以使用numeral.js

                            numeral(1.341).format('0.00') // 1.34
                            numeral(1.345).format('0.00') // 1.35
                            

                            【讨论】:

                              【解决方案30】:
                              <script src="https://code.jquery.com/jquery-3.6.0.js" integrity="sha256-H+K7U5CnXl1h5ywQfKtSj8PCmoN9aaq30gDh27Xc0jk=" crossorigin="anonymous"></script>
                              <script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.mask/1.14.16/jquery.mask.min.js" integrity="sha512-pHVGpX7F/27yZ0ISY+VVjyULApbDlD0/X0rgGbTqCE7WFW5MezNTWG/dnhtbBuICzsd0WQPgpE4REBLv+UqChw==" crossorigin="anonymous"></script>
                              
                              
                              <input type="text" class = 'item_price' name="price" min="1.00" placeholder="Enter Price" value="{{ old('price') }}" step="">
                              
                              <script> 
                              $(document).ready(function() {
                                  $('.item_price').mask('00000.00', { reverse: true });
                              });
                              </script>
                              

                              【讨论】:

                                猜你喜欢
                                • 2011-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 1970-01-01
                                • 2014-05-03
                                • 1970-01-01
                                • 1970-01-01
                                相关资源
                                最近更新 更多