Javascript:将舍入后的数字格式化为N个小数


104

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

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

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

有任何想法吗?


9
通常,您可以使用toFixed()developer.mozilla.org/En/Core_JavaScript_1.5_Reference/…),但这在IE中是有问题的:stackoverflow.com/questions/661562/…;您必须编写自己的版本...
Christoph

1
@hoju-可能更改接受的答案-David的答案对于IE8 +是正确的,而接受的答案在所有浏览器中都有一些严重的错误。
robocat

@robocat:你是认真的吗?
Guffa

Answers:


25

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

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

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

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


3
toFixed是越野车..例如十进制:1.02449999998如果u dec.toFixed(4)=> 1.0244。它应该是1.0245。
Bat_Programmer

2
@deepeshk但是toFixed()在四舍五入后使用小数点末尾填充会有什么问题?
pauloya 2011年

10
@deepeshk在什么浏览器中?刚刚在Chrome 17中尝试过并1.02449999998.toFixed(4)正确返回1.0245
马特·鲍尔

3
@MarkTomlin:看来您有一个字符串而不是数字。
Guffa

1
.toFixed()在现代浏览器中表现出色(我测试了Chrome,Firefox,IE11,IE8)。@Bat_Programmer-请阐明您认为哪些浏览器存在该错误。
robocat

243

我认为这里提供了一种更简单的方法,并且该方法Number.toFixed()已经在JavaScript中实现。

只需写:

var myNumber = 2;

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

等等...


哪里有,何州?我查看了其他答案,但没有发现任何人报告toFixed功能有问题。谢谢
David

@David:例如,答案中提到了这一点。
Guffa 2015年

13
注意:toFixed()返回一个字符串。
乔丹·阿塞诺

2
@JordanArseno,可以使用parseInt(myNumber.toFixed(intVar))进行修复。返回整数值,或parseFloat(myNumber.toFixed(floatVar)); 如果用户有小数位,则返回浮点数。
斯蒂芬·罗梅罗

50

我找到了一个方法。这是克里斯托夫的代码,带有修复程序:

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”感到好奇,请在此处阅读使用数组构造函数重复字符的详细信息。


以2或3的精度传递值708.3333333333333会为我带来708.00的返回值。我需要2个小数位,在Chrome和IE 9中。toFixed(2)满足了我的需求。
2013年

这不是常见的方式,例如toFixed(16.775,2)返回16.77。将数字转换为字符串,然后转换是唯一的方法。
Hiway

2
此方法存在一个错误:toFixed(-0.1111,2)返回0.11,即负号丢失。
马特

效果很好,除了我在末尾添加了parseFloat(result)。值得编辑。
Artur Barseghyan 2015年

16

总有一种更好的做事方式。

var number = 51.93999999999761;

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

做就是了:

number.toPrecision(4);

其结果将是:51.94


2
如果加100,该怎么办?您是否需要将其更改为number.toPrecision(5)?
JohnnyBizzle '16

2
是。31.939383.toPrecision(4)>“ 31.94” / 131.939383.toPrecision(4)>“ 131.9”
ReSpawN

6

类似PHP的舍入方法

下面的代码可用于将您自己的Math.round版本添加到带有精度参数的名称空间中。与上述示例中的十进制舍入不同,它不执行字符串间的转换,而precision参数的工作方式与PHP和Excel相同,其中,正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开发人员的Math.round()参考


2

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

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;
}

您的代码中有一个错误。我尝试固定(2.01,4),结果为“ 2.100”。如果我找到解决它的方法,我将其发布为对此问题的解答。
埃里亚斯·扎马里亚

@ mikez302:填充计算被减一;应该可以正常工作了,但是如果它仍然坏了,请随时再次困扰我……
Christoph

很奇怪。当我在firefox 17中打开firebug控制台运行此功能时,它冻结了整个浏览器,就像js陷入了一个无限循环。即使我不console.log输出。如果我没有激活Firebug,则不会发生错误。
SublymeRick

1
更新,我在chrome中运行它,我得到:未捕获的RangeError:关于toFixed函数调用,超出了最大调用堆栈大小。
SublymeRick

@SublymeRick:我不知道为什么会这样;在黑暗中拍摄:尝试重命名功能...
Christoph

2

我认为下面的功能可以帮助

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


2

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

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

过去,当我编写数据处理E-Slate组件时,不得不在Java上使用这种逻辑。那是因为我发现将0多次加0.1会得到一些意想不到的长小数部分(这是由于浮点运算所致)。

用户在格式编号处始终显示2个小数位的注释称为此技术缩放。

有人提到有些情况无法按预期进行,在http://www.jacklmoore.com/notes/rounding-in-javascript/中建议使用以下方法:

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

顺便说一句,假定是有希望的未来的H / W架构:nextplatform.com/2019/07/08/...
乔治Birbilis

-2

如果您不太在意舍入,只需添加toFixed(x),然后删除尾随的0es和点(如有必要)即可。这不是一个快速的解决方案。

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”。
Juan Carrey 2015年
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.