29

问题

我试图在控制台中以米为单位建立一个高度列表,从 1.20m 开始,到 2.50m 结束。

我使用了这段代码:

var heights = [];
for ( var i=1.20, l=2.5; i<l; i+=0.01 ){

    heights.push(i);

}

heights = heights.join('\n');

如果console.log( heights )我得到:

1.2
1.21
1.22
1.23
...

但是在 1.37 我开始得到:

1.37
1.3800000000000001
1.3900000000000001
1.4000000000000001
1.4100000000000001
1.4200000000000002
1.4300000000000002

问题

  • 这是怎么回事?
  • 我如何解决它?

演示

var heights = [];
for ( var i=1.20, l=2.5; i<l; i+=0.01 ){

    heights.push(i);

}

var heights = heights.join('\n');

document.querySelector('#output').innerText = heights;
<!DOCTYPE html>
<html>
<head>
<meta charset=utf-8 />
<title>JS Bin</title>
</head>
<body>
  <div id="output"></div>
</body>
</html>

4

6 回答 6

17

你做得很好。问题在于浮点数的不准确性。

为什么浮点数如此不准确?

如果您希望显示此数字,请使用:

heights[i].toFixed(2);

请注意,它返回一个字符串,如果您想执行更多的数字运算,toFixed()则必须转换回浮点数 ( )。parseFloat()

于 2013-10-10T08:27:51.797 回答
8

这仅仅是因为数学在 JavaScript 中是如何工作的,你可以找到很多解释它的答案——比如这个。最简单的解决方案是只做 100 次,然后在添加到数组时除以,例如

var heights = [], i, l;
for (i = 120; i < 250; i += 1){    
    heights.push(i / 100);    
}

你可以使用toFixed,但这会给你一个String结果。

于 2013-10-10T08:26:46.553 回答
2

这是由于浮点数是如何在内部存储的,它不是 JavaScript 特定的。您可以使用.toFixed()以所需精度存储数字的字符串表示形式,因此:

heights.push(i.toFixed(2));

如果您想避免存储字符串,然后将它们转换回实际数字,您可以将步长相乘,使其变为整数,然后存储除法:

for (var i = 120; i <= 250; ++i) {
    heights.push(i / 100);
}

除了您现在拥有数字这一事实之外,不同之处在于多个 of0.1以单一精度表示,例如,2.4而不是"2.40".

于 2013-10-10T08:27:20.260 回答
1

这是因为机器使用以 2 为基数,而您使用的以 10 为基数的数字无法用浮点数以 2 为基数准确表示。

您可以使用此库对其进行格式化:https ://github.com/dtrebbien/BigDecimal.js

于 2013-10-10T08:28:05.880 回答
1

如前所述,toFixed()返回StringparseFloat()转换StringFloat. parseFloat()还删除了尾随零,这是有道理的,但不适用于我的用例。

Float这是使用和保留尾随零的迭代示例。

var i = 0.9,
  floats = [];

while (i < 2) {
  i = (i + 0.1).toFixed(1);
  floats.push(i);
  i = parseFloat(i);
}
console.log(floats);


[ '1.0',
  '1.1',
  '1.2',
  '1.3',
  '1.4',
  '1.5',
  '1.6',
  '1.7',
  '1.8',
  '1.9',
  '2.0' ]

如果不需要尾随零,则循环可以简化为:

while (i < 2) {
  floats.push(i);
  i = parseFloat((i + 0.1).toFixed(1));
}
于 2014-04-20T05:49:02.793 回答
0

使用toFixed(float)方法,限制逗号后面的位数

heights.push(i.toFixed(2));
于 2013-10-10T08:28:37.147 回答