【问题标题】:How to format a float in javascript?如何在javascript中格式化浮点数?
【发布时间】:2010-10-14 06:39:34
【问题描述】:

在 JavaScript 中,当从浮点数转换为字符串时,我怎样才能得到小数点后 2 位数字?例如,0.34 而不是 0.3445434。

【问题讨论】:

  • 只是一些吹毛求疵:除了前两位数字之外,您是要“砍掉”所有数字,还是要四舍五入到两位数?

标签: javascript floating-point


【解决方案1】:
var result = Math.round(original*100)/100;

The specifics,以防代码无法自我解释。

编辑:...或者只使用@987654322@,正如Tim Büthe 所建议的那样。忘了那个,谢谢(和赞成)提醒:)

【讨论】:

  • 我在“Highchart”库中使用它,它不接受字符串值,因此 toFixed 对我不起作用,Math.round 解决了我的问题,谢谢
  • toFixed() 将模仿 printf() 在 C 中所做的事情。但是,toFixed()Math.round() 会以不同的方式处理舍入。在这种情况下,toFixed() 将具有与Math.floor() 相同的效果(假设您事先将原始值乘以 10^n,并使用 n 位调用 toFixed())。答案的“正确性”在很大程度上取决于 OP 想要什么,并且两者都以自己的方式“正确”。
  • 不幸的是,这里提出的方法不是一个好的方法,因为它可能会导致意外的值,如 4.99999999998 等,因为二进制基的工作方式。请改用 toFixed。
【解决方案2】:
var x = 0.3445434
x = Math.round (x*100) / 100 // this will make nice rounding

【讨论】:

  • Math.round(1.015 * 100) / 100 给出 1.01 而我们期望它是 1.02?
  • console.log(Math.round((1.015 + 0.00001) * 100) / 100) // 1.02 这将解决上述情况
【解决方案3】:

有四舍五入的功能。例如:

var x = 5.0364342423;
print(x.toFixed(2));

将打印 5.04。

编辑: Fiddle

【讨论】:

  • 我建议不要在浏览器中使用 print()
  • 注意这一点,toFixed() 返回一个字符串:var x = 5.036432346; var y = x.toFixed(2) + 100; y 将等于"5.03100"
  • 请注意 (1e100).toFixed(2) === "1e+100"
  • 另外,请注意舍入不一致:(0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)...
  • 如果您搜索 toFixed 的等效项但具有一致的舍入,请使用 toLocaleString : (0.345).toLocaleString('en-EN',{minimumFractionDigits:2, maximumFractionDigits:2})
【解决方案4】:

使用toFixed()时要小心:

首先,使用数字的二进制表示对数字进行四舍五入,这可能会导致意外行为。例如

(0.595).toFixed(2) === '0.59'

而不是'0.6'

其次,toFixed() 存在 IE 错误。在 IE(至少到版本 7,没有检查 IE8)中,以下情况成立:

(0.9).toFixed(0) === '0'

听从 kkyy 的建议或使用自定义的toFixed() 函数可能是个好主意,例如

function toFixed(value, precision) {
    var power = Math.pow(10, precision || 0);
    return String(Math.round(value * power) / power);
}

【讨论】:

  • 是的,这在创建代码来预测价格时非常重要。谢谢! +1
  • 我建议在返回值中添加本机.toFixed() 方法,这将增加所需的精度,例如:return (Math.round(value * power) / power).toFixed(precision); 并将值作为字符串返回。否则,对于较小的小数,20 的精度将被忽略
  • 关于toFixed 的注意事项:注意提高精度会产生意想不到的结果:(1.2).toFixed(16) === "1.2000000000000000",而(1.2).toFixed(17) === "1.19999999999999996"(在 Firefox/Chrome 中;在 IE8 中,由于较低IE8 内部可以提供的精度)。
  • 请注意,即使(0.598).toFixed(2) 也不会产生0.6。它产生0.60 :)
  • 另外,小心舍入不一致:(0.335).toFixed(2) == 0.34 == (0.345).toFixed(2).
【解决方案5】:

也许您还需要小数分隔符?这是我刚刚制作的一个函数:

function formatFloat(num,casasDec,sepDecimal,sepMilhar) {
    if (num < 0)
    {
        num = -num;
        sinal = -1;
    } else
        sinal = 1;
    var resposta = "";
    var part = "";
    if (num != Math.floor(num)) // decimal values present
    {
        part = Math.round((num-Math.floor(num))*Math.pow(10,casasDec)).toString(); // transforms decimal part into integer (rounded)
        while (part.length < casasDec)
            part = '0'+part;
        if (casasDec > 0)
        {
            resposta = sepDecimal+part;
            num = Math.floor(num);
        } else
            num = Math.round(num);
    } // end of decimal part
    while (num > 0) // integer part
    {
        part = (num - Math.floor(num/1000)*1000).toString(); // part = three less significant digits
        num = Math.floor(num/1000);
        if (num > 0)
            while (part.length < 3) // 123.023.123  if sepMilhar = '.'
                part = '0'+part; // 023
        resposta = part+resposta;
        if (num > 0)
            resposta = sepMilhar+resposta;
    }
    if (sinal < 0)
        resposta = '-'+resposta;
    return resposta;
}

【讨论】:

    【解决方案6】:

    所有这些使用乘数的解决方案都存在问题。不幸的是,kyy 和 Christoph 的解决方案都是错误的。

    请测试您的代码是否有 2 位小数的数字 551.175 - 它会四舍五入到 551.17 而它应该是 551.18 !但如果你测试前。 451.175 没问题 - 451.18。所以乍一看很难发现这个错误。

    问题在于乘法:尝试 551.175 * 100 = 55117.49999999999(ups!)

    所以我的想法是在使用 Math.round() 之前先用 toFixed() 处理它;

    function roundFix(number, precision)
    {
        var multi = Math.pow(10, precision);
        return Math.round( (number * multi).toFixed(precision + 1) ) / multi;
    }
    

    【讨论】:

    • 这就是js中算术的问题:(551.175 * 10 * 10) !== (551.175 * 100)。您必须使用小数增量来移动逗号以获得​​非实数小数结果。
    • +1 表示注意到这一点,但 toFixed 也会受到影响 — (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)... 无论使用哪种方法,最好在舍入前添加一个 epsilon。
    【解决方案7】:

    另一个需要注意的问题是toFixed() 可能会在数字末尾产生不必要的零。 例如:

    var x=(23-7.37)
    x
    15.629999999999999
    x.toFixed(6)
    "15.630000"
    

    这个想法是使用RegExp 清理输出:

    function humanize(x){
      return x.toFixed(6).replace(/\.?0*$/,'');
    }
    

    RegExp 匹配尾随零(以及可选的小数点)以确保它也适合整数。

    humanize(23-7.37)
    "15.63"
    humanize(1200)
    "1200"
    humanize(1200.03)
    "1200.03"
    humanize(3/4)
    "0.75"
    humanize(4/3)
    "1.333333"
    

    【讨论】:

    • Number.prototype.minFixed = function(decimals) { return this.toFixed(decimals).replace(/\.?0*$/, ""); }
    • 这应该被接受,尾随零很烦人,我正在寻找这个解决方案,gj。
    • 尾随零可能很烦人,但这正是方法名称“toFixed”承诺要做的事情;)
    【解决方案8】:

    使用乘法或除法无法避免以 x.xx5 作为实际值的价格舍入不一致。如果您需要在客户端计算正确的价格,您应该以美分为单位保留所有金额。这是由于 JavaScript 中数值的内部表示的性质。请注意,Excel 也存在同样的问题,因此大多数人不会注意到由这种现象引起的小错误。但是,当您将大量计算值相加时,误差可能会累积,围绕这一点有一个完整的理论,涉及计算顺序和其他方法以最小化最终结果中的误差。为了强调十进制值的问题,请注意 0.1 + 0.2 在 JavaScript 中并不完全等于 0.3,而 1 + 2 等于 3。

    【讨论】:

    • 解决方案是将整个部分和小数部分分开,并将它们表示为以 10 为底的整数,而不是使用浮点数,在这里它对 prettyPrint 没有问题,但通常你必须在两者之间进行选择一个基数和另一个基数,一个实数表示和另一个,每个都有其问题
    • “Excel 也有同样的问题”。来源?
    【解决方案9】:
    /** don't spend 5 minutes, use my code **/
    function prettyFloat(x,nbDec) { 
        if (!nbDec) nbDec = 100;
        var a = Math.abs(x);
        var e = Math.floor(a);
        var d = Math.round((a-e)*nbDec); if (d == nbDec) { d=0; e++; }
        var signStr = (x<0) ? "-" : " ";
        var decStr = d.toString(); var tmp = 10; while(tmp<nbDec && d*tmp < nbDec) {decStr = "0"+decStr; tmp*=10;}
        var eStr = e.toString();
        return signStr+eStr+"."+decStr;
    }
    
    prettyFloat(0);      //  "0.00"
    prettyFloat(-1);     // "-1.00"
    prettyFloat(-0.999); // "-1.00"
    prettyFloat(0.5);    //  "0.50"
    

    【讨论】:

      【解决方案10】:
      function trimNumber(num, len) {
        const modulu_one = 1;
        const start_numbers_float=2;
        var int_part = Math.trunc(num);
        var float_part = String(num % modulu_one);
            float_part = float_part.slice(start_numbers_float, start_numbers_float+len);
        return int_part+'.'+float_part;
      }
      

      【讨论】:

      • 很好的答案,除了你缺少分号(不,在 es6 中分号并没有过时,在某些情况下我们仍然必须使用它们)。我还必须将最后一行编辑为:return float_part ? int_part+'.'+float_part : int_part;,否则如果您传递整数,它会返回最后带有点的数字(示例输入:2100,输出:2100.
      【解决方案11】:

      我使用这段代码来格式化浮点数。它基于toPrecision(),但它去除了不必要的零。我欢迎有关如何简化正则表达式的建议。

      function round(x, n) {
          var exp = Math.pow(10, n);
          return Math.floor(x*exp + 0.5)/exp;
      }
      

      使用示例:

      function test(x, n, d) {
          var rounded = rnd(x, d);
          var result = rounded.toPrecision(n);
          result = result.replace(/\.?0*$/, '');
          result = result.replace(/\.?0*e/, 'e');
          result = result.replace('e+', 'e');
          return result;  
      }
      
      document.write(test(1.2000e45, 3, 2) + '=' + '1.2e45' + '<br>');
      document.write(test(1.2000e+45, 3, 2) + '=' + '1.2e45' + '<br>');
      document.write(test(1.2340e45, 3, 2) + '=' + '1.23e45' + '<br>');
      document.write(test(1.2350e45, 3, 2) + '=' + '1.24e45' + '<br>');
      document.write(test(1.0000, 3, 2) + '=' + '1' + '<br>');
      document.write(test(1.0100, 3, 2) + '=' + '1.01' + '<br>');
      document.write(test(1.2340, 4, 2) + '=' + '1.23' + '<br>');
      document.write(test(1.2350, 4, 2) + '=' + '1.24' + '<br>');
      

      【讨论】:

        【解决方案12】:

        我猜这里的关键是先正确四舍五入,然后你可以将它转换为字符串。

        function roundOf(n, p) {
            const n1 = n * Math.pow(10, p + 1);
            const n2 = Math.floor(n1 / 10);
            if (n1 >= (n2 * 10 + 5)) {
                return (n2 + 1) / Math.pow(10, p);
            }
            return n2 / Math.pow(10, p);
        }
        
        // All edge cases listed in this thread
        roundOf(95.345, 2); // 95.35
        roundOf(95.344, 2); // 95.34
        roundOf(5.0364342423, 2); // 5.04
        roundOf(0.595, 2); // 0.60
        roundOf(0.335, 2); // 0.34
        roundOf(0.345, 2); // 0.35
        roundOf(551.175, 2); // 551.18
        roundOf(0.3445434, 2); // 0.34
        

        现在您可以使用 toFixed(p) 安全地格式化该值。 因此,对于您的具体情况:

        roundOf(0.3445434, 2).toFixed(2); // 0.34
        

        【讨论】:

        • .toFixed(2) 将数字转换为字符串,将数字四舍五入以保留两位小数
        【解决方案13】:

        如果你想要没有圆形的字符串,你可以使用这个正则表达式(也许不是最有效的方法......但真的很容易)

        (2.34567778).toString().match(/\d+\.\d{2}/)[0]
        // '2.34'
        

        【讨论】:

          【解决方案14】:

          countDecimals = value => {
              if (Math.floor(value) === value) return 0;
              let stringValue = value.toString().split(".")[1];
              if (stringValue) {
                return value.toString().split(".")[1].length
                  ? value.toString().split(".")[1].length
                  : 0;
              } else {
                return 0;
              }
            };
            
          formatNumber=(ans)=>{
              let decimalPlaces = this.countDecimals(ans);
              ans = 1 * ans;
              if (decimalPlaces !== 0) {
                let onePlusAns = ans + 1;
                let decimalOnePlus = this.countDecimals(onePlusAns);
                if (decimalOnePlus < decimalPlaces) {
                  ans = ans.toFixed(decimalPlaces - 1).replace(/\.?0*$/, "");
                } else {
                  let tenMulAns = ans * 10;
                  let decimalTenMul = this.countDecimals(tenMulAns);
                  if (decimalTenMul + 1 < decimalPlaces) {
                    ans = ans.toFixed(decimalPlaces - 1).replace(/\.?0*$/, "");
                  }
                }
              }
          }

          我只是将值加 1 并计算原始值和添加值中存在的小数位数。如果在添加比原始十进制数字少一位后找到十进制数字,我只需使用(原始小数 - 1)调用 toFixed()。我还通过将原始值乘以 10 进行检查,并遵循相同的逻辑,以防加一不会减少多余的小数位。 在 JS 中处理浮点数舍入的简单解决方法。在我尝试过的大多数情况下都有效。

          【讨论】:

            猜你喜欢
            • 2015-12-12
            • 1970-01-01
            • 2014-05-08
            • 2016-01-02
            • 2018-10-28
            • 2013-04-19
            • 2019-07-11
            • 1970-01-01
            相关资源
            最近更新 更多