【问题标题】:Formatting a number with exactly two decimals in JavaScript在 JavaScript 中格式化正好有两位小数的数字
【发布时间】:2010-12-16 03:30:21
【问题描述】:

我有这行代码将我的数字四舍五入到小数点后两位。但我得到的数字是这样的:10.8、2.4 等。这些不是我的小数点后两位的想法,所以我该如何改进以下数字?

Math.round(price*Math.pow(10,2))/Math.pow(10,2);

我想要 10.80、2.40 等数字。我可以使用 jQuery。

【问题讨论】:

  • 您的代码正是我想要的(对于较小的 JSON 文件,将浮点精度降低到小数点后 7 位)跳过 Math.pow 以获取速度 val = Math.round(val * 10000000) / 10000000) ;
  • 由于currently-accepted answer 可以说是由于数字中固有的不精确性加剧(0.5650.5751.005)而对广泛的值给出了错误的结果,我可以建议看看再次在this answer,这让他们正确吗?
  • 也许你想包含一个 JavaScript 的 sprintf 库stackoverflow.com/questions/610406/…
  • 用小数位移位和舍入方法正确舍入后,可以使用number.toFixed(x) 方法将其转换为所需数量的零的字符串。例如。使用跨浏览器方法将1.34 舍入到1.3,然后添加1 个零并使用1.3.toFixed(2) 转换为字符串(得到"1.30")。
  • 现在是 2020 年,JavaScript 中没有简单的原生方式来简单地对数字进行四舍五入。哇。

标签: javascript rounding decimal-point


【解决方案1】:

Christian C. Salvadó's answer 之上构建,执行以下操作将输出Number 类型,并且似乎也可以很好地处理舍入:

const roundNumberToTwoDecimalPlaces = (num) => Number(new Intl.NumberFormat('en-US', {
  minimumFractionDigits: 2,
  maximumFractionDigits: 2,
}).format(num));

roundNumberToTwoDecimalPlaces(1.344); // => 1.34
roundNumberToTwoDecimalPlaces(1.345); // => 1.35

上面和已经提到的区别是你在使用它时不需要.format()链接[,它输出一个Number类型]。

【讨论】:

    【解决方案2】:

    我不知道为什么我不能在以前的答案中添加评论(也许我是盲目的,我不知道),但我使用@Miguel 的答案想出了一个解决方案:

    function precise_round(num,decimals) {
       return Math.round(num*Math.pow(10, decimals)) / Math.pow(10, decimals);
    }
    

    还有它的两个 cmets(来自 @bighostkim 和 @Imre):

    • precise_round(1.275,2) 不返回 1.28 的问题
    • precise_round(6,2) 的问题没有返回 6.00(如他所愿)。

    我的最终解决方案如下:

    function precise_round(num,decimals) {
        var sign = num >= 0 ? 1 : -1;
        return (Math.round((num*Math.pow(10,decimals)) + (sign*0.001)) / Math.pow(10,decimals)).toFixed(decimals);
    }
    

    如您所见,我必须添加一点“更正”(不是这样,但由于 Math.round 是有损的 - 您可以在 jsfiddle.net 上查看 - 这是我知道的唯一方法要解决这个问题)。它将 0.001 添加到已填充的数字上,因此它在十进制值的右侧添加了一个 1 三个 0s。所以应该可以放心使用。

    之后我添加了.toFixed(decimal) 以始终以正确的格式输出数字(带有正确的小数位数)。

    差不多就是这样。好好利用它;)

    编辑:添加了“更正”负数的功能。

    【讨论】:

    • “更正”大部分是安全的,但例如precise_round(1.27499,2) 现在也返回 1.28... 不是 Math.round 有损;计算机内部存储浮点值的方式是。基本上,在数据到达您的函数之前,您注定会因某些值而失败:)
    • @Imre,你说得对。这就是为什么我解释这个 0.001 在那里做什么,以防有人想让它“更精确”甚至删除它(如果你碰巧有一台每个浮点数为 2 MB 的超级计算机,我不要认为这里有人这样做;)
    • 实际上,language specification 非常具体地使用 64 位作为数值,因此拥有/使用超级计算机不会改变任何事情 :)
    • 对于 0.001,您可以根据小数的长度添加许多零来替换。所以..
    【解决方案3】:

    快速简单

    parseFloat(number.toFixed(2))
    

    示例

    let number = 2.55435930
    
    let roundedString = number.toFixed(2)    // "2.55"
    
    let twoDecimalsNumber = parseFloat(roundedString)    // 2.55
    
    let directly = parseFloat(number.toFixed(2))    // 2.55
    

    【讨论】:

    • 搜索了一段时间,终于成功了,简单易行
    • 是的,上面提到了关于 toFixed 的警告,它可能会返回不准确的舍入,比如 1.005。您应该在回答中提及这些警告。
    • parseFloat(13.99999).toFixed(2) > "14.00" parseFloat(parseFloat(13.99999).toFixed(2)) > 14
    【解决方案4】:

    一般来说,小数舍入是通过缩放来完成的:round(num * p) / p

    简单实现

    使用以下带有中间数字的函数,您将获得预期的上舍入值,或者有时取决于输入的下舍入值。

    inconsistency 舍入可能会在客户端代码中引入难以检测的错误。

    function naiveRound(num, decimalPlaces) {
        var p = Math.pow(10, decimalPlaces);
        return Math.round(num * p) / p;
    }
    
    console.log( naiveRound(1.245, 2) );  // 1.25 correct (rounded as expected)
    console.log( naiveRound(1.255, 2) );  // 1.25 incorrect (should be 1.26)

    更好的实现

    通过将数字转换为 指数表示法 中的字符串,正数按预期四舍五入。 但是,请注意,负数与正数的舍入方式不同。

    事实上,它执行的规则基本上等同于"round half up",您会看到round(-1.005, 2) 的计算结果为-1,即使round(1.005, 2) 的计算结果为1.01lodash _.round 方法使用了这种技术。

    /**
     * Round half up ('round half towards positive infinity')
     * Uses exponential notation to avoid floating-point issues.
     * Negative numbers round differently than positive numbers.
     */
    function round(num, decimalPlaces) {
        num = Math.round(num + "e" + decimalPlaces);
        return Number(num + "e" + -decimalPlaces);
    }
    
    // test rounding of half
    console.log( round(0.5, 0) );  // 1
    console.log( round(-0.5, 0) ); // 0
    
    // testing edge cases
    console.log( round(1.005, 2) );   // 1.01
    console.log( round(2.175, 2) );   // 2.18
    console.log( round(5.015, 2) );   // 5.02
    
    console.log( round(-1.005, 2) );  // -1
    console.log( round(-2.175, 2) );  // -2.17
    console.log( round(-5.015, 2) );  // -5.01

    如果您希望在舍入负数时保持通常的行为,则需要在调用 Math.round() 之前将负数转换为正数,然后在返回之前将它们转换回负数。

    // Round half away from zero
    function round(num, decimalPlaces) {
        num = Math.round(Math.abs(num) + "e" + decimalPlaces) * Math.sign(num);
        return Number(num + "e" + -decimalPlaces);
    }
    

    有一种不同的纯数学技术来执行舍入到最近(使用"round half away from zero"),其中在调用舍入函数之前应用epsilon 校正

    简单地说,我们在四舍五入之前将可能的最小浮点值(= 1.0 ulp;最后一个单位)添加到数字中。这将移动到数字之后的下一个可表示值,远离零。

    /**
     * Round half away from zero ('commercial' rounding)
     * Uses correction to offset floating-point inaccuracies.
     * Works symmetrically for positive and negative numbers.
     */
    function round(num, decimalPlaces) {
        var p = Math.pow(10, decimalPlaces);
        var e = Number.EPSILON * num * p;
        return Math.round((num * p) + e) / p;
    }
    
    // test rounding of half
    console.log( round(0.5, 0) );  // 1
    console.log( round(-0.5, 0) ); // -1
    
    // testing edge cases
    console.log( round(1.005, 2) );  // 1.01
    console.log( round(2.175, 2) );  // 2.18
    console.log( round(5.015, 2) );  // 5.02
    
    console.log( round(-1.005, 2) ); // -1.01
    console.log( round(-2.175, 2) ); // -2.18
    console.log( round(-5.015, 2) ); // -5.02

    这是为了抵消在十进制数编码期间可能出现的隐式round-off error,尤其是在最后一个小数位具有“5”的数字,例如 1.005、2.675 和 16.235。实际上,十进制的1.005被编码为64位二进制浮点的1.0049999999999999;而十进制的1234567.005 编码为64 位二进制浮点数的1234567.0049999998882413

    值得注意的是,最大二进制 round-off error 取决于 (1) 数字的大小和 (2) 相对机器 epsilon (2^-52)。

    【讨论】:

      【解决方案5】:

      这是https://stackoverflow.com/a/21323330/916734 的 TypeScript 实现。它还使用函数来干掉事情,并允许可选的数字偏移量。

      export function round(rawValue: number | string, precision = 0, fractionDigitOffset = 0): number | string {
        const value = Number(rawValue);
        if (isNaN(value)) return rawValue;
      
        precision = Number(precision);
        if (precision % 1 !== 0) return NaN;
      
        let [ stringValue, exponent ] = scientificNotationToParts(value);
      
        let shiftExponent = exponentForPrecision(exponent, precision, Shift.Right);
        const enlargedValue = toScientificNotation(stringValue, shiftExponent);
        const roundedValue = Math.round(enlargedValue);
      
        [ stringValue, exponent ] = scientificNotationToParts(roundedValue);
        const precisionWithOffset = precision + fractionDigitOffset;
        shiftExponent = exponentForPrecision(exponent, precisionWithOffset, Shift.Left);
      
        return toScientificNotation(stringValue, shiftExponent);
      }
      
      enum Shift {
        Left = -1,
        Right = 1,
      }
      
      function scientificNotationToParts(value: number): Array<string> {
        const [ stringValue, exponent ] = value.toString().split('e');
        return [ stringValue, exponent ];
      }
      
      function exponentForPrecision(exponent: string, precision: number, shift: Shift): number {
        precision = shift * precision;
        return exponent ? (Number(exponent) + precision) : precision;
      }
      
      function toScientificNotation(value: string, exponent: number): number {
        return Number(`${value}e${exponent}`);
      }
      

      【讨论】:

        【解决方案6】:

        要使用定点符号格式化数字,您可以简单地使用toFixed 方法:

        (10.8).toFixed(2); // "10.80"
        
        var num = 2.4;
        alert(num.toFixed(2)); // "2.40"
        

        注意toFixed() 返回一个字符串。

        重要提示:请注意,toFixed 在 90% 的情况下不会四舍五入,它会返回四舍五入的值,但在很多情况下,它不起作用。

        例如:

        2.005.toFixed(2) === "2.00"

        更新:

        现在,您可以使用Intl.NumberFormat 构造函数。它是ECMAScript Internationalization API Specification (ECMA402) 的一部分。它有pretty good browser support,甚至包括IE11,它是fully supported in Node.js

        const formatter = new Intl.NumberFormat('en-US', {
           minimumFractionDigits: 2,      
           maximumFractionDigits: 2,
        });
        
        console.log(formatter.format(2.005)); // "2.01"
        console.log(formatter.format(1.345)); // "1.35"

        您也可以使用toLocaleString 方法,该方法在内部将使用Intl API:

        const format = (num, decimals) => num.toLocaleString('en-US', {
           minimumFractionDigits: 2,      
           maximumFractionDigits: 2,
        });
        
        
        console.log(format(2.005)); // "2.01"
        console.log(format(1.345)); // "1.35"

        此 API 还为您提供了多种格式选项,例如千位分隔符、货币符号等。

        【讨论】:

        • 不能在所有浏览器中一致地工作,即(0.09).toFixed(1); 在 IE8 中给出 0.0
        • fixed不圆,可以先做:(Math.round(0.09)).toFixed(1);
        • @rekans:这是错误的。 Math.Round(0.09) 将返回 0 所以这总是给 0.0...
        • 这在大多数情况下是个坏主意,在某些情况下它会将数字转换为字符串或浮点数。
        • 这里必须同意@AshBlue...这仅对格式化值表示是安全的。可能会通过进一步的计算破坏代码。否则Math.round(value*100)/100 更适合 2DP。
        【解决方案7】:

        我找到了一个非常简单的方法为我解决了这个问题并且可以使用或改编:

        td[row].innerHTML = price.toPrecision(price.toFixed(decimals).length
        

        【讨论】:

          【解决方案8】:

          几个月前我从这篇文章中得到了一些想法,但这里的答案以及其他帖子/博客的答案都无法处理所有情况(例如,负数和我们的测试人员发现的一些“幸运数字”)。最后,我们的测试人员没有发现下面这个方法有什么问题。粘贴我的代码的 sn-p:

          fixPrecision: function (value) {
              var me = this,
                  nan = isNaN(value),
                  precision = me.decimalPrecision;
          
              if (nan || !value) {
                  return nan ? '' : value;
              } else if (!me.allowDecimals || precision <= 0) {
                  precision = 0;
              }
          
              //[1]
              //return parseFloat(Ext.Number.toFixed(parseFloat(value), precision));
              precision = precision || 0;
              var negMultiplier = value < 0 ? -1 : 1;
          
              //[2]
              var numWithExp = parseFloat(value + "e" + precision);
              var roundedNum = parseFloat(Math.round(Math.abs(numWithExp)) + 'e-' + precision) * negMultiplier;
              return parseFloat(roundedNum.toFixed(precision));
          },
          

          我也有代码 cmets(抱歉,我已经忘记了所有细节)...我在这里发布我的答案以供将来参考:

          9.995 * 100 = 999.4999999999999
          Whereas 9.995e2 = 999.5
          This discrepancy causes Math.round(9.995 * 100) = 999 instead of 1000.
          Use e notation instead of multiplying /dividing by Math.Pow(10,precision).
          

          【讨论】:

            【解决方案9】:

            这是我的 1 行解决方案:Number((yourNumericValueHere).toFixed(2));

            会发生什么:

            1) 首先,您将.toFixed(2) 应用到要舍入小数位的数字上。请注意,这会将值从数字转换为字符串。所以如果你使用 Typescript,它会抛出这样的错误:

            “类型‘字符串’不可分配给类型‘数字’”

            2) 要取回数值或将字符串转换为数值,只需对所谓的“字符串”值应用Number() 函数即可。

            为了清楚起见,看下面的例子:

            示例: 我有一个小数点后最多 5 位的金额,我想将其缩短到小数点后 2 位。我是这样做的:

            var price = 0.26453;
            var priceRounded = Number((price).toFixed(2));
            console.log('Original Price: ' + price);
            console.log('Price Rounded: ' + priceRounded);

            【讨论】:

              【解决方案10】:

              通过这些示例,您在尝试将数字 1.005 舍入时仍然会遇到错误,解决方案是使用 Math.js 之类的库或此函数:

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

              【讨论】:

                【解决方案11】:

                四舍五入

                function round_down(value, decPlaces) {
                    return Math.floor(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
                }
                

                总结

                function round_up(value, decPlaces) {
                    return Math.ceil(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
                }
                

                最近的圆

                function round_nearest(value, decPlaces) {
                    return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
                }
                

                合并https://stackoverflow.com/a/7641824/1889449https://www.kirupa.com/html5/rounding_numbers_in_javascript.htm 谢谢 他们。

                【讨论】:

                  【解决方案12】:

                  100% 工作!!!试试看

                  <html>
                       <head>
                        <script>
                        function replacePonto(){
                          var input = document.getElementById('qtd');
                          var ponto = input.value.split('.').length;
                          var slash = input.value.split('-').length;
                          if (ponto > 2)
                                  input.value=input.value.substr(0,(input.value.length)-1);
                  
                          if(slash > 2)
                                  input.value=input.value.substr(0,(input.value.length)-1);
                  
                          input.value=input.value.replace(/[^0-9.-]/,'');
                  
                          if (ponto ==2)
                  	input.value=input.value.substr(0,(input.value.indexOf('.')+3));
                  
                  if(input.value == '.')
                  	input.value = "";
                                }
                        </script>
                        </head>
                        <body>
                           <input type="text" id="qtd" maxlength="10" style="width:140px" onkeyup="return replacePonto()">
                        </body>
                      </html>

                  【讨论】:

                  • 欢迎来到 SO。请阅读此how-to-answer 并按照指南回答。
                  【解决方案13】:

                  parse = function (data) {
                         data = Math.round(data*Math.pow(10,2))/Math.pow(10,2);
                         if (data != null) {
                              var lastone = data.toString().split('').pop();
                              if (lastone != '.') {
                                   data = parseFloat(data);
                              }
                         }
                         return data;
                    };
                  
                  $('#result').html(parse(200)); // output 200
                  $('#result1').html(parse(200.1)); // output 200.1
                  $('#result2').html(parse(200.10)); // output 200.1
                  $('#result3').html(parse(200.109)); // output 200.11
                  <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.0.0/jquery.min.js"></script>
                  <div id="result"></div>
                  <div id="result1"></div>
                  <div id="result2"></div>
                  <div id="result3"></div>

                  【讨论】:

                    【解决方案14】:

                    通过引用使用此响应:https://stackoverflow.com/a/21029698/454827

                    我构建了一个函数来获取动态的小数位数:

                    function toDec(num, dec)
                    {
                            if(typeof dec=='undefined' || dec<0)
                                    dec = 2;
                    
                            var tmp = dec + 1;
                            for(var i=1; i<=tmp; i++)
                                    num = num * 10;
                    
                            num = num / 10;
                            num = Math.round(num);
                            for(var i=1; i<=dec; i++)
                                    num = num / 10;
                    
                            num = num.toFixed(dec);
                    
                            return num;
                    }
                    

                    这里的工作示例:https://jsfiddle.net/wpxLduLc/

                    【讨论】:

                      【解决方案15】:

                      这是一个老话题,但仍然在 Google 搜索结果中名列前茅,并且提供的解决方案共享相同的浮点小数问题。这是我使用的(非常通用的)函数,thanks to MDN

                      function round(value, exp) {
                        if (typeof exp === 'undefined' || +exp === 0)
                          return Math.round(value);
                      
                        value = +value;
                        exp = +exp;
                      
                        if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
                          return NaN;
                      
                        // Shift
                        value = value.toString().split('e');
                        value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));
                      
                        // Shift back
                        value = value.toString().split('e');
                        return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
                      }
                      

                      如我们所见,我们没有遇到这些问题:

                      round(1.275, 2);   // Returns 1.28
                      round(1.27499, 2); // Returns 1.27
                      

                      这种通用性还提供了一些很酷的东西:

                      round(1234.5678, -2);   // Returns 1200
                      round(1.2345678e+2, 2); // Returns 123.46
                      round("123.45");        // Returns 123
                      

                      现在,要回答 OP 的问题,必须输入:

                      round(10.8034, 2).toFixed(2); // Returns "10.80"
                      round(10.8, 2).toFixed(2);    // Returns "10.80"
                      

                      或者,为了更简洁、更通用的函数:

                      function round2Fixed(value) {
                        value = +value;
                      
                        if (isNaN(value))
                          return NaN;
                      
                        // Shift
                        value = value.toString().split('e');
                        value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + 2) : 2)));
                      
                        // Shift back
                        value = value.toString().split('e');
                        return (+(value[0] + 'e' + (value[1] ? (+value[1] - 2) : -2))).toFixed(2);
                      }
                      

                      你可以这样称呼它:

                      round2Fixed(10.8034); // Returns "10.80"
                      round2Fixed(10.8);    // Returns "10.80"
                      

                      各种示例和测试(感谢@t-j-crowder!):

                      function round(value, exp) {
                        if (typeof exp === 'undefined' || +exp === 0)
                          return Math.round(value);
                      
                        value = +value;
                        exp = +exp;
                      
                        if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
                          return NaN;
                      
                        // Shift
                        value = value.toString().split('e');
                        value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));
                      
                        // Shift back
                        value = value.toString().split('e');
                        return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
                      }
                      function naive(value, exp) {
                        if (!exp) {
                          return Math.round(value);
                        }
                        var pow = Math.pow(10, exp);
                        return Math.round(value * pow) / pow;
                      }
                      function test(val, places) {
                        subtest(val, places);
                        val = typeof val === "string" ? "-" + val : -val;
                        subtest(val, places);
                      }
                      function subtest(val, places) {
                        var placesOrZero = places || 0;
                        var naiveResult = naive(val, places);
                        var roundResult = round(val, places);
                        if (placesOrZero >= 0) {
                          naiveResult = naiveResult.toFixed(placesOrZero);
                          roundResult = roundResult.toFixed(placesOrZero);
                        } else {
                          naiveResult = naiveResult.toString();
                          roundResult = roundResult.toString();
                        }
                        $("<tr>")
                          .append($("<td>").text(JSON.stringify(val)))
                          .append($("<td>").text(placesOrZero))
                          .append($("<td>").text(naiveResult))
                          .append($("<td>").text(roundResult))
                          .appendTo("#results");
                      }
                      test(0.565, 2);
                      test(0.575, 2);
                      test(0.585, 2);
                      test(1.275, 2);
                      test(1.27499, 2);
                      test(1234.5678, -2);
                      test(1.2345678e+2, 2);
                      test("123.45");
                      test(10.8034, 2);
                      test(10.8, 2);
                      test(1.005, 2);
                      test(1.0005, 2);
                      table {
                        border-collapse: collapse;
                      }
                      table, td, th {
                        border: 1px solid #ddd;
                      }
                      td, th {
                        padding: 4px;
                      }
                      th {
                        font-weight: normal;
                        font-family: sans-serif;
                      }
                      td {
                        font-family: monospace;
                      }
                      <table>
                        <thead>
                          <tr>
                            <th>Input</th>
                            <th>Places</th>
                            <th>Naive</th>
                            <th>Thorough</th>
                          </tr>
                        </thead>
                        <tbody id="results">
                        </tbody>
                      </table>
                      <script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>

                      【讨论】:

                      • 怎么没有一个简单的方法来做到这一点? ES6 来拯救?
                      • 感谢您发布 MDN polyfill。在链接的 MDN 页面上,polyfill 不再存在。我想知道为什么它被删除了...
                      • 如何使用它来获得小数点后第一位的值,比如 3.0421 应该返回 3.0?
                      • @RIni,您应该能够使用round(3.0421, 1) 来获取3 作为数字或round(3.0421, 1).toFixed(1) 来获取'3.0' 作为字符串。
                      【解决方案16】:

                      我没有找到这个问题的准确解决方案,所以我创建了自己的:

                      function inprecise_round(value, decPlaces) {
                        return Math.round(value*Math.pow(10,decPlaces))/Math.pow(10,decPlaces);
                      }
                      
                      function precise_round(value, decPlaces){
                          var val = value * Math.pow(10, decPlaces);
                          var fraction = (Math.round((val-parseInt(val))*10)/10);
                      
                          //this line is for consistency with .NET Decimal.Round behavior
                          // -342.055 => -342.06
                          if(fraction == -0.5) fraction = -0.6;
                      
                          val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
                          return val;
                      }
                      

                      例子:

                      function inprecise_round(value, decPlaces) {
                        return Math.round(value * Math.pow(10, decPlaces)) / Math.pow(10, decPlaces);
                      }
                      
                      function precise_round(value, decPlaces) {
                        var val = value * Math.pow(10, decPlaces);
                        var fraction = (Math.round((val - parseInt(val)) * 10) / 10);
                      
                        //this line is for consistency with .NET Decimal.Round behavior
                        // -342.055 => -342.06
                        if (fraction == -0.5) fraction = -0.6;
                      
                        val = Math.round(parseInt(val) + fraction) / Math.pow(10, decPlaces);
                        return val;
                      }
                      
                      // This may produce different results depending on the browser environment
                      console.log("342.055.toFixed(2)         :", 342.055.toFixed(2)); // 342.06 on Chrome & IE10
                      
                      console.log("inprecise_round(342.055, 2):", inprecise_round(342.055, 2)); // 342.05
                      console.log("precise_round(342.055, 2)  :", precise_round(342.055, 2));   // 342.06
                      console.log("precise_round(-342.055, 2) :", precise_round(-342.055, 2));  // -342.06
                      
                      console.log("inprecise_round(0.565, 2)  :", inprecise_round(0.565, 2));   // 0.56
                      console.log("precise_round(0.565, 2)    :", precise_round(0.565, 2));     // 0.57

                      【讨论】:

                      • 谢谢。这是测试这个的小曲:jsfiddle.net/lamarant/ySXuF。我在返回值之前将 toFixed() 应用于该值,它将正确数量的零附加到返回值的末尾。
                      • 不适用于 value=0,004990845956707237 和 inprecise_round(value,8) 返回 0,00499085 但它必须返回 0,00499084
                      • inprecise_round(9.999, 2) 在需要 9.99 的地方给出 10
                      【解决方案17】:

                      我通常将它添加到我的个人库中,经过一些建议并使用@TIMINeutron 解决方案,然后使其适应十进制长度,这个最适合:

                      function precise_round(num, decimals) {
                         var t = Math.pow(10, decimals);   
                         return (Math.round((num * t) + (decimals>0?1:0)*(Math.sign(num) * (10 / Math.pow(100, decimals)))) / t).toFixed(decimals);
                      }
                      

                      将适用于报告的异常。

                      【讨论】:

                      • precise_round(1.275,2) 是 1.27?
                      • @Imre 将返回值更改为 (Math.round(num*Math.pow(10,decimals))/Math.pow(10,decimals)).toFixed(2);你将不再有这个问题。
                      • 如果你的第二个函数按原样被拾取,你在哪里声明“sign”和“dec”不应该将它们作为未定义的吗?
                      • 我在 IE 中为 missign 签名方法添加了一个工作区:gist.github.com/ArminVieweg/28647e735aa6efaba401
                      • @Armin 您的修复也使它在 Safari 中工作。原来的功能在 Safari 中不起作用。
                      【解决方案18】:
                      Number(Math.round(1.005+'e2')+'e-2'); // 1.01
                      

                      这对我有用:Rounding Decimals in JavaScript

                      【讨论】:

                        【解决方案19】:

                        您也可以使用.toPrecision() 方法和一些自定义代码,并且无论 int 部分的长度如何,始终向上舍入到第 n 个小数位。

                        function glbfrmt (number, decimals, seperator) {
                            return typeof number !== 'number' ? number : number.toPrecision( number.toString().split(seperator)[0].length + decimals);
                        }
                        

                        你也可以把它做成一个插件来更好地使用。

                        【讨论】:

                          【解决方案20】:

                          一种 100% 确定您得到 2 位小数的方法的方法:

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

                          如果这会导致舍入错误,您可以使用 James 在评论中解释的以下内容:

                          (Math.round((num * 1000)/10)/100).toFixed(2)
                          

                          【讨论】:

                          • 这是最好、最简单的方法。但是,由于浮点数学运算,1.275 * 100 = 127.49999999999999,这可能会导致舍入中的小错误。为了解决这个问题,我们可以乘以 1000 除以 10,即 (1.275 * 1000)/10 = 127.5。如下:var answer = (Math.round((num * 1000)/10)/100).toFixed(2);
                          • (Math.round((1.015 * 1000)/10)/100).toFixed(2) 仍然给出 1.01,不应该是 1.02 吗?
                          • (Math.round((99999999999999.9999 * 1000)/10)/100).toFixed(4) 返回"100000000000000.0000"
                          【解决方案21】:

                          这非常简单,并且和其他任何一个一样有效:

                          function parseNumber(val, decimalPlaces) {
                              if (decimalPlaces == null) decimalPlaces = 0
                              var ret = Number(val).toFixed(decimalPlaces)
                              return Number(ret)
                          }
                          

                          由于 toFixed() 只能在数字上调用,并且不幸地返回一个字符串,这会在两个方向上为您完成所有解析。您可以传递一个字符串或一个数字,并且每次都返回一个数字!调用 parseNumber(1.49) 会给你 1,而 parseNumber(1.49,2) 会给你 1.50。就像他们中最好的一样!

                          【讨论】:

                            【解决方案22】:

                            /*Due to all told stuff. You may do 2 things for different purposes:
                            When showing/printing stuff use this in your alert/innerHtml= contents:
                            YourRebelNumber.toFixed(2)*/
                            
                            var aNumber=9242.16;
                            var YourRebelNumber=aNumber-9000;
                            alert(YourRebelNumber);
                            alert(YourRebelNumber.toFixed(2));
                            
                            /*and when comparing use:
                            Number(YourRebelNumber.toFixed(2))*/
                            
                            if(YourRebelNumber==242.16)alert("Not Rounded");
                            if(Number(YourRebelNumber.toFixed(2))==242.16)alert("Rounded");
                            
                            /*Number will behave as you want in that moment. After that, it'll return to its defiance.
                            */

                            【讨论】:

                              【解决方案23】:
                              Number(((Math.random() * 100) + 1).toFixed(2))
                              

                              这将返回一个从 1 到 100 的随机数,四舍五入到小数点后 2 位。

                              【讨论】:

                                【解决方案24】:
                                (Math.round((10.2)*100)/100).toFixed(2)
                                

                                这应该产生:10.20

                                (Math.round((.05)*100)/100).toFixed(2)
                                

                                这应该产生:0.05

                                (Math.round((4.04)*100)/100).toFixed(2)
                                

                                这应该产生:4.04

                                等等

                                【讨论】:

                                  【解决方案25】:

                                  我正在修复修改器的问题。 仅支持 2 位小数。

                                  $(function(){
                                    //input number only.
                                    convertNumberFloatZero(22); // output : 22.00
                                    convertNumberFloatZero(22.5); // output : 22.50
                                    convertNumberFloatZero(22.55); // output : 22.55
                                    convertNumberFloatZero(22.556); // output : 22.56
                                    convertNumberFloatZero(22.555); // output : 22.55
                                    convertNumberFloatZero(22.5541); // output : 22.54
                                    convertNumberFloatZero(22222.5541); // output : 22,222.54
                                  
                                    function convertNumberFloatZero(number){
                                  	if(!$.isNumeric(number)){
                                  		return 'NaN';
                                  	}
                                  	var numberFloat = number.toFixed(3);
                                  	var splitNumber = numberFloat.split(".");
                                  	var cNumberFloat = number.toFixed(2);
                                  	var cNsplitNumber = cNumberFloat.split(".");
                                  	var lastChar = splitNumber[1].substr(splitNumber[1].length - 1);
                                  	if(lastChar > 0 && lastChar < 5){
                                  		cNsplitNumber[1]--;
                                  	}
                                  	return Number(splitNumber[0]).toLocaleString('en').concat('.').concat(cNsplitNumber[1]);
                                    };
                                  });
                                  &lt;script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"&gt;&lt;/script&gt;

                                  【讨论】:

                                    【解决方案26】:

                                    将您的十进制值四舍五入,然后使用toFixed(x) 作为您预期的数字。

                                    function parseDecimalRoundAndFixed(num,dec){
                                      var d =  Math.pow(10,dec);
                                      return (Math.round(num * d) / d).toFixed(dec);
                                    }
                                    

                                    打电话

                                    parseDecimalRoundAndFixed(10.800243929,4) => 10.80 parseDecimalRoundAndFixed(10.807243929,2) => 10.81

                                    【讨论】:

                                      【解决方案27】:

                                      以下内容放在某个全局范围内:

                                      Number.prototype.getDecimals = function ( decDigCount ) {
                                         return this.toFixed(decDigCount);
                                      }
                                      

                                      然后试试

                                      var a = 56.23232323;
                                      a.getDecimals(2); // will return 56.23
                                      

                                      更新

                                      请注意,toFixed() 只能用于0-20 之间的小数位数,即a.getDecimals(25) 可能会产生 javascript 错误,因此您可以添加一些额外的检查,即

                                      Number.prototype.getDecimals = function ( decDigCount ) {
                                         return ( decDigCount > 20 ) ? this : this.toFixed(decDigCount);
                                      }
                                      

                                      【讨论】:

                                        【解决方案28】:

                                        这是一个简单的

                                        function roundFloat(num,dec){
                                            var d = 1;
                                            for (var i=0; i<dec; i++){
                                                d += "0";
                                            }
                                            return Math.round(num * d) / d;
                                        }
                                        

                                        alert(roundFloat(1.79209243929,4));一样使用

                                        Jsfiddle

                                        【讨论】:

                                          【解决方案29】:

                                          浮点值的问题在于它们试图用固定数量的位来表示无限数量的(连续)值。所以自然而然地,在比赛中一定会有一些损失,你会被一些价值观所咬。

                                          当计算机将 1.275 存储为浮点值时,它实际上不会记住它是 1.275 还是 1.27499999999999993,甚至是 1.27500000000000002。这些值在四舍五入到两位小数后应该会给出不同的结果,但它们不会,因为对于计算机,它们在存储为浮点值后看起来完全相同,并且无法恢复丢失的数据。任何进一步的计算只会累积这种不精确性。

                                          因此,如果精度很重要,您必须从一开始就避免使用浮点值。最简单的选择是

                                          • 使用devoted library
                                          • 使用字符串存储和传递值(伴随字符串操作)
                                          • 使用整数(例如,您可以传递实际价值的百分之一的金额,例如以美分为单位的金额,而不是以美元为单位的金额)

                                          比如用整数来存储百分位数时,求实际值的函数就很简单了:

                                          function descale(num, decimals) {
                                              var hasMinus = num < 0;
                                              var numString = Math.abs(num).toString();
                                              var precedingZeroes = '';
                                              for (var i = numString.length; i <= decimals; i++) {
                                                  precedingZeroes += '0';
                                              }
                                              numString = precedingZeroes + numString;
                                              return (hasMinus ? '-' : '') 
                                                  + numString.substr(0, numString.length-decimals) 
                                                  + '.' 
                                                  + numString.substr(numString.length-decimals);
                                          }
                                          
                                          alert(descale(127, 2));
                                          

                                          对于字符串,您需要四舍五入,但它仍然易于管理:

                                          function precise_round(num, decimals) {
                                              var parts = num.split('.');
                                              var hasMinus = parts.length > 0 && parts[0].length > 0 && parts[0].charAt(0) == '-';
                                              var integralPart = parts.length == 0 ? '0' : (hasMinus ? parts[0].substr(1) : parts[0]);
                                              var decimalPart = parts.length > 1 ? parts[1] : '';
                                              if (decimalPart.length > decimals) {
                                                  var roundOffNumber = decimalPart.charAt(decimals);
                                                  decimalPart = decimalPart.substr(0, decimals);
                                                  if ('56789'.indexOf(roundOffNumber) > -1) {
                                                      var numbers = integralPart + decimalPart;
                                                      var i = numbers.length;
                                                      var trailingZeroes = '';
                                                      var justOneAndTrailingZeroes = true;
                                                      do {
                                                          i--;
                                                          var roundedNumber = '1234567890'.charAt(parseInt(numbers.charAt(i)));
                                                          if (roundedNumber === '0') {
                                                              trailingZeroes += '0';
                                                          } else {
                                                              numbers = numbers.substr(0, i) + roundedNumber + trailingZeroes;
                                                              justOneAndTrailingZeroes = false;
                                                              break;
                                                          }
                                                      } while (i > 0);
                                                      if (justOneAndTrailingZeroes) {
                                                          numbers = '1' + trailingZeroes;
                                                      }
                                                      integralPart = numbers.substr(0, numbers.length - decimals);
                                                      decimalPart = numbers.substr(numbers.length - decimals);
                                                  }
                                              } else {
                                                  for (var i = decimalPart.length; i < decimals; i++) {
                                                      decimalPart += '0';
                                                  }
                                              }
                                              return (hasMinus ? '-' : '') + integralPart + (decimals > 0 ? '.' + decimalPart : '');
                                          }
                                          
                                          alert(precise_round('1.275', 2));
                                          alert(precise_round('1.27499999999999993', 2));
                                          

                                          请注意,此函数四舍五入到最近,从零开始,而IEEE 754 建议四舍五入到最近,到偶数作为浮点运算的默认行为.这些修改留给读者作为练习:)

                                          【讨论】:

                                          • precise_round("999999999999999999.9999", 2) 返回"1000000000000000000.00"
                                          • 我希望它是999999999999999999.99
                                          • @FaizanHussainRabbani 1000000000000000000.00 是这个四舍五入的正确结果 - 9.9999 比 9.99 更接近 10.00。舍入是在数学中定义的函数,并在 IEEE 754 中为计算标准化。如果您想要不同的结果,则需要不同的函数。编写测试以指定各种输入所需的结果,并编写满足这些测试的代码。
                                          【解决方案30】:

                                          @heridev 和我在 jQuery 中创建了一个小函数。

                                          你可以试试下一个:

                                          HTML

                                          <input type="text" name="one" class="two-digits"><br>
                                          <input type="text" name="two" class="two-digits">​
                                          

                                          jQuery

                                          // apply the two-digits behaviour to elements with 'two-digits' as their class
                                          $( function() {
                                              $('.two-digits').keyup(function(){
                                                  if($(this).val().indexOf('.')!=-1){         
                                                      if($(this).val().split(".")[1].length > 2){                
                                                          if( isNaN( parseFloat( this.value ) ) ) return;
                                                          this.value = parseFloat(this.value).toFixed(2);
                                                      }  
                                                   }            
                                                   return this; //for chaining
                                              });
                                          });
                                          

                                          ​ 在线演示:

                                          http://jsfiddle.net/c4Wqn/

                                          【讨论】:

                                          • 我很欣赏这个贡献,但我认为将 DOM 元素和 jQuery 添加到混合中似乎超出了问题的范围。
                                          • 您不应该听 keyup 事件,因为它看起来很糟糕,并且在您使用脚本添加内容时不会激活。我宁愿听input 事件。这不会产生闪烁效果,并且在您使用 JS 访问字段时也会触发
                                          猜你喜欢
                                          • 1970-01-01
                                          • 2011-06-04
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 2021-09-03
                                          • 1970-01-01
                                          • 1970-01-01
                                          • 1970-01-01
                                          相关资源
                                          最近更新 更多