6

这个很奇怪,因为我让它在这个小提琴中运行,但它在主小提琴中不起作用。我相信代码是一样的。

这是主要功能:

window.setInterval(function(){
    for(var i=0; i < companies.length; i++) {
        var randomVal = (Math.random()*(10 - (-10) + 1)) + (-10);
        randomVal = randomVal / 100;
        randomVal = Number(randomVal.toFixed(2));
        companies[i].price += randomVal;
        //companies[i].price = companies[i].price.toFixed(2);
        $('#price'+i).html(companies[i].price);
    }
}, 1000);

像这样的值34.569999999999986没有被削减到34.56. 知道有什么问题吗?

4

5 回答 5

12

这与在二进制浮点值和十进制表示之间转换时发生的常见问题有关。看看这个小提琴,它就像你的“工作”小提琴,但我改变了这个price值,让它也坏了。

这是一个更简单的演示,它直接解决了问题的核心:http: //jsfiddle.net/2NHSM/4/

如您所见, 的输出1.23 - 10.22999999999999998。这显然有一点偏差,但这与计算机表示数字的方式有关。

计算机将数字保存为二进制数字。1.23实际上是二进制的“重复十进制”(就像 1/7 在十进制中重复一样),因此没有 100% 准确的存储方法。结果,当您减去时,1.23 - 1您会得到一个略微偏离的答案,因为1.23一开始就不是准确的。

你的情况也发生了同样的事情。要修复它,只需toFixed在显示值之前使用,而不是在添加其他内容之前使用。


更新

这是一个工作小提琴:http: //jsfiddle.net/2NHSM/6/


更新 2

另请注意,toFixed可能会有意外的舍入行为。在控制台中尝试以下操作:

1.35.toFixed(1);
// => 1.4
1.45.toFixed(1);
// => 1.4

您可能想Math.round改用。

Math.round(1.35 * 10) / 10
// => 1.4
Math.round(1.45 * 10) / 10
// => 1.5
于 2012-12-22T02:39:41.573 回答
3

浮点数是近似值,因此当您添加时,它们并不总是以干净的数字结束。显示时只需调用 toFixed :

companies[i].price += randomVal;
$('#price'+i).html(companies[i].price.toFixed(2));

演示


这就是你//companies[i].price = companies[i].price.toFixed(2);没有工作的原因:

toFixed()返回一个字符串,所以第一次调用后,companies[i].price是一个字符串。当您这样做时companies[i].price += randomVal;,它正在执行字符串连接而不是数字加法。它会产生类似的东西:

577.05
577.050.05
577.050.050.1

所以你不能再调用 toFixed 了,因为:

  1. 这是一个字符串
  2. 它甚至不是一个有效的数字

那么,你将如何解决这个问题?通过乘以 1(或Number())将其转换为数字;

companies[i].price += randomVal;
companies[i].price = companies[i].price.toFixed(2)*1;
$('#price'+i).html(companies[i].price);

演示

使用这些解决方案中的任何一个,toFixed()都不需要第一次调用。

于 2012-12-22T02:39:25.377 回答
1

那是因为在应用之后,.toFixed()您将该值添加到另一个变量,这会导致精度再次失控。

而是使用它来显示:

$('#price'+i).html(companies[i].price.toFixed(2));
于 2012-12-22T02:40:18.827 回答
0

它在您的第一个示例中起作用的原因是因为您在每次通过时将 price 的值重置为 577。

试试这个,它在计算总和后对价格调用 .toFixed(2) 并将其返回给您的变量。

您可能会放弃在 randomVal 上调用的第一个 .toFixed。

 window.setInterval(function(){
    for(var i=0; i < companies.length; i++) {
        var randomVal = (Math.random()*(10 - (-10) + 1)) + (-10);
        randomVal = randomVal / 100;
        randomVal = Number(randomVal.toFixed(2));
        companies[i].price += randomVal;
        companies[i].price = Number(companies[i].price.toFixed(2)); 
        $('#price'+i).html(companies[i].price);
    }
}, 1000);
于 2012-12-22T02:56:17.110 回答
0

您的转换数据是响应 [25] 并按照以下步骤操作。

var i = parseFloat(response[25]).toFixed(2)
console.log(i)//-6527.34
于 2016-05-17T11:50:03.100 回答