【问题标题】:JavaScript adding decimal numbers issue [duplicate]JavaScript添加十进制数字问题[重复]
【发布时间】:2012-05-15 11:36:17
【问题描述】:

所以我正在制作一个将两个数字(十进制数)相加的脚本,我遇到了问题。

http://jsfiddle.net/DerekL/esqnC/

我做了脚本,结果很不错:

0.1 + 0.5  //0.6
0.2 + 0.3  //0.5

但很快我就明白了:

0.1 + 0.2  //0.30000000000000004
0.01 + 0.06  //0.06999999999999999

而且我觉得它不合适。我知道使用有限位浮点数是一个缺点,但我找不到解决这个问题的方法。

Math.ceil   //No
Math.floor  //No
.slice      //No

更新

是否可以先将数字乘以 1000,然后将它们相加,然后再除以 1000?

【问题讨论】:

  • 这不是错误,只是实际值具有固定的精度,因此对实际值进行计算可能会导致一些小错误。
  • Math.round(0.1 + 0.2) 为 0。
  • @Gazler - 我需要如何解决它,而不是为什么会发生。
  • 解决这个问题的方法是对整数执行操作。因此,如果您使用货币价值,请不要使用美元,而要使用美分。 (在计算结束时,只需除以 100 即可获得以美元为单位的价值)。
  • @Gazler 恭喜:)。当然,您将应用一些数学来确定您需要的精度。另一方面,每个人都理解造成问题中情况的问题,但有一点我不清楚:预期的输出是什么?

标签: javascript numbers


【解决方案1】:

使用toFixed 将其转换为去掉一些小数位的字符串,然后再将其转换回数字。

+(0.1 + 0.2).toFixed(12) // 0.3

看起来 IE 的 toFixed 有一些奇怪的行为,所以如果你需要支持 IE,这样的东西可能会更好:

Math.round((0.1 + 0.2) * 1e12) / 1e12

【讨论】:

  • 不错,工作:jsfiddle.net/esqnC/5
  • @Derek 在阅读了作为重复链接的问题的一些 cmets 后,看起来 IE 的 toFixed 可能会截断而不是舍入。这样做可能更安全:Math.round((0.1 + 0.2) * 1e12) / 1e12
  • @GGG Math.round() 是个好主意 :)
  • @GGG - 看起来这是最终的解决方法。谢谢!
  • @GGG:可能。你toFixed 解决方案无论如何都在这里工作:jsfiddle.net/KooiInc/D7ULx
【解决方案2】:
function add(){
    var first=parseFloat($("#first").val());
    var second=parseFloat($("#second").val());
    $("#result").val(+(first+second).toFixed(2));
}

DEMO.

【讨论】:

  • parseFloat(11200030006000.126) 仍然出现 11200030006000.127
【解决方案3】:

这是浮点的常见问题。

toFixedparseFloat 结合使用。

这是 JavaScript 中的example

function roundNumber(number, decimals) {
    var newnumber = new Number(number+'').toFixed(parseInt(decimals));
    return parseFloat(newnumber); 
}

0.1 + 0.2;                    //=> 0.30000000000000004
roundNumber( 0.1 + 0.2, 12 ); //=> 0.3

【讨论】:

  • 试试 11200030006000.125 + 0.001
  • 你说得对,我和 KooiInc 将其更新为 12 位精度。仍然 GGG 的 Math.round((0.1 + 0.2) * 1e12) / 1e12 解决方案很优雅!
  • 但现在结果是:11200030006000.125 + 0.001 = 11200030006000.127。应该是 11200030006000.126 ...
  • 确实很奇怪。我还尝试了 GGG 的解决方案 (jsfiddle.net/49HGP/6),它的评估结果也为 11200030006000.127。你知道为什么会发生这种情况吗?
  • 对于这么大的数字,我认为这只是精度问题,而不是在二进制中重复小数。 10000000000000.126 == 10000000000000.127 // true
【解决方案4】:

测试这个 Javascript:

var arr = [1234563995.721, 12345691212.718, 1234568421.5891, 12345677093.49284];

var sum = 0;
for( var i = 0; i < arr.length; i++ ) {
    sum += arr[i];
}

alert( "fMath(sum) = " + Math.round( sum * 1e12 ) / 1e12 );
alert( "fFixed(sum) = " + sum.toFixed( 5 ) );

结论

不要使用Math.round( (## + ## + ... + ##) * 1e12) / 1e12

改为使用( ## + ## + ... + ##).toFixed(5) )

在 IE 9 中,toFixed 运行良好。

【讨论】:

  • 请给出结果示例,或者至少创建一个小提琴
  • 你的结论是什么?
  • new Number((11200030006000.125 + 0.001).toFixed(5)) 仍然 = 11200030006000.127,但如果将其保留为字符串 (11200030006000.125 + 0.001).toFixed(5) = (112000) .toFixed(5) 所以 Number 是四舍五入的。这仍然是一个奇怪的问题,你必须对你的小数位做出真正的假设。仍在寻找我不必担心的准确解决方案
猜你喜欢
  • 1970-01-01
  • 2016-06-02
  • 1970-01-01
  • 1970-01-01
  • 2020-03-18
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多