【问题标题】:Javascript: formatting a rounded number to N decimalsJavascript:将四舍五入的数字格式化为 N 个小数
【发布时间】:2011-01-14 08:06:00
【问题描述】:

在 JavaScript 中,将数字四舍五入到 N 位小数的典型方法是:

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

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

console.log(roundNumber(0.1 + 0.2, 2));
console.log(roundNumber(2.1234, 2));

但是,这种方法将舍入到 最大 N 个小数位,而我希望 始终 舍入到 N 个小数位。例如,“2.0”将四舍五入为“2”。

有什么想法吗?

【问题讨论】:

标签: javascript math rounding decimal-point


【解决方案1】:

我认为这里给出了一个更简单的方法,并且方法 Number.toFixed() 已经在 J​​avaScript 中实现。

简单写:

var myNumber = 2;

myNumber.toFixed(2); //returns "2.00"
myNumber.toFixed(1); //returns "2.0"

等等……

【讨论】:

  • 哪里提到,hoju?我查看了其他答案,但没有发现任何人报告 toFixed 函数有问题。谢谢
  • @David:例如,在对答案的评论中提到了这一点。
  • 注意:toFixed() 返回一个字符串。
  • @JordanArseno 这可以使用 parseInt(myNumber.toFixed(intVar));返回一个整数值,或 parseFloat(myNumber.toFixed(floatVar));如果用户有小数位,则返回浮点数。
【解决方案2】:

我找到了办法。这是 Christoph 的修复代码:

function toFixed(value, precision) {
    var precision = precision || 0,
        power = Math.pow(10, precision),
        absValue = Math.abs(Math.round(value * power)),
        result = (value < 0 ? '-' : '') + String(Math.floor(absValue / power));

    if (precision > 0) {
        var fraction = String(absValue % power),
            padding = new Array(Math.max(precision - fraction.length, 0) + 1).join('0');
        result += '.' + padding + fraction;
    }
    return result;
}

如果您对我为什么添加“+ 1”感到好奇,请阅读使用数组构造函数 here 重复字符的详细信息。

【讨论】:

  • 传入精度为 2 或 3 的值 708.333333333333 对我来说返回值 708.00。我需要这个小数点后 2 位,在 Chrome 和 IE 9 中 .toFixed(2) 满足了我的需求。
  • 这不是常用的方式,例如 toFixed(16.775, 2) 返回 16.77。将数字转换为字符串然后转换是唯一的方法。
  • 这个方法有个bug:toFixed(-0.1111, 2)返回0.11,即负号丢失。
  • 效果很好,除了我在最后添加了 parseFloat(result) 。值得编辑。
【解决方案3】:

这不是取整问题,而是显示问题。一个数字不包含有关有效数字的信息;值 2 与 2.0000000000000 相同。当您将四舍五入的值转换为字符串时,您可以使其显示一定数量的数字。

您可以在数字后添加零,例如:

var s = number.toString();
if (s.indexOf('.') == -1) s += '.';
while (s.length < s.indexOf('.') + 4) s += '0';

(请注意,这里假设客户端的区域设置使用句点作为小数分隔符,代码需要更多工作才能用于其他设置。)

【讨论】:

  • toFixed 有问题..例如小数点:1.02449999998 如果你做 dec.toFixed(4) => 1.0244。它应该是 1.0245。
  • @deepeshk 但是在四舍五入后使用toFixed() 在末尾填充小数会有什么问题?
  • @deepeshk 在什么浏览器中?刚刚在 Chrome 17 中尝试过,1.02449999998.toFixed(4) 正确返回1.0245
  • @MarkTomlin:那么看来你有一个字符串而不是一个数字。
  • .toFixed() 在现代浏览器中表现出色(我测试了 Chrome、Firefox、IE11、IE8)。 @Bat_Programmer - 请说明您认为 哪些 浏览器存在该错误。
【解决方案4】:

总有更好的做事方式。

var number = 51.93999999999761;

我想得到四位数的精度:51.94

只是做:

number.toPrecision(4);

结果将是:51.94

【讨论】:

  • 如果加 100 会怎样?需要改成 number.toPrecision(5) 吗?
  • 是的。 31.939383.toPrecision(4) > "31.94" / 131.939383.toPrecision(4) > "131.9"
【解决方案5】:

类 PHP 舍入方法

下面的代码可用于将您自己的 Math.round 版本添加到您自己的名称空间中,该名称空间采用精度参数。与上面示例中的小数舍入不同,这不执行字符串之间的转换,并且精度参数的工作方式与 PHP 和 Excel 相同,正 1 将舍入到小数点后 1 位,-1 将舍入到十位。

var myNamespace = {};
myNamespace.round = function(number, precision) {
    var factor = Math.pow(10, precision);
    var tempNumber = number * factor;
    var roundedTempNumber = Math.round(tempNumber);
    return roundedTempNumber / factor;
};

myNamespace.round(1234.5678, 1); // 1234.6
myNamespace.round(1234.5678, -1); // 1230

来自Mozilla Developer reference for Math.round()

【讨论】:

    【解决方案6】:

    这适用于四舍五入到 N 位(如果您只想截断到 N 位,请删除 Math.round 调用并使用 Math.trunc ):

    function roundN(value, digits) {
       var tenToN = 10 ** digits;
       return /*Math.trunc*/(Math.round(value * tenToN)) / tenToN;
    }
    

    过去我在编写data manipulation E-Slate components 时不得不求助于 Java 的这种逻辑。那是因为我发现多次将 0.1 加到 0 上,你最终会得到一些意想不到的长小数部分(这是由于浮点运算造成的)。

    Format number to always show 2 decimal places 的用户评论称这种技术为缩放。

    有些人提到有些情况没有按预期四舍五入,http://www.jacklmoore.com/notes/rounding-in-javascript/ 建议改为:

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

    【讨论】:

    【解决方案7】:

    希望能正常工作的代码(没有做太多测试):

    function toFixed(value, precision) {
        var precision = precision || 0,
            neg = value < 0,
            power = Math.pow(10, precision),
            value = Math.round(value * power),
            integral = String((neg ? Math.ceil : Math.floor)(value / power)),
            fraction = String((neg ? -value : value) % power),
            padding = new Array(Math.max(precision - fraction.length, 0) + 1).join('0');
    
        return precision ? integral + '.' +  padding + fraction : integral;
    }
    

    【讨论】:

    • 您的代码有错误。我尝试了 toFixed(2.01, 4) 并得到了“2.100”的结果。如果我找到修复它的方法,我会将其发布为这个问题的答案。
    • @mikez302:填充计算被关闭了;现在应该可以工作了,但如果它仍然坏了,请随时再次打扰我......
    • 很奇怪。当我在 firefox 17 中打开 firebug 控制台运行此功能时,它会冻结整个浏览器,就像 js 陷入无限循环一样。即使我没有 console.log 输出。如果我没有激活 firebug,则不会发生错误。
    • 更新,我在 chrome 中运行它,我得到:Uncaught RangeError:关于 toFixed 函数调用的最大调用堆栈大小超出。
    • @SublymeRick:我不知道为什么会这样;在黑暗中拍摄:尝试重命名函数...
    【解决方案8】:

    我认为下面的函数可以提供帮助

    function roundOff(value,round) {
       return (parseInt(value * (10 ** (round + 1))) - parseInt(value * (10 ** round)) * 10) > 4 ? (((parseFloat(parseInt((value + parseFloat(1 / (10 ** round))) * (10 ** round))))) / (10 ** round)) : (parseFloat(parseInt(value * (10 ** round))) / ( 10 ** round));
    }
    

    用法:roundOff(600.23458,2); 将返回 600.23

    【讨论】:

      【解决方案9】:

      如果您并不真正关心舍入,只需添加一个 toFixed(x) ,然后在必要时删除尾随的 0 和点。这不是一个快速的解决方案。

      function format(value, decimals) {
          if (value) {
              value = value.toFixed(decimals);            
          } else {
              value = "0";
          }
          if (value.indexOf(".") < 0) { value += "."; }
          var dotIdx = value.indexOf(".");
          while (value.length - dotIdx <= decimals) { value += "0"; } // add 0's
      
          return value;
      }
      

      【讨论】:

      • 我尝试了format(1.2, 5),得到了1.2,而我期待1.20000
      • 对不起@EliasZamaria,一开始没看懂。我已经编辑了帖子。请注意,当值未定义时,它将返回“0.0000”。
      猜你喜欢
      • 1970-01-01
      • 2022-12-03
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-10-13
      • 2010-09-14
      相关资源
      最近更新 更多