【问题标题】:Javascript rounding issue when summing values [duplicate]求和值时的Javascript舍入问题[重复]
【发布时间】:2012-07-31 00:36:38
【问题描述】:

可能重复:
Is JavaScript's Math broken?

用户在前两个文本框中输入值,然后在输入时使用 Javascript(抱歉,没有 jQuery,我还没有做到这一点)来计算精确的总和并将总和四舍五入为 2 位数。

为什么会出现舍入错误,我可以做些什么来纠正它?

非常感谢。

嗯....ParseFloat?错误的数据类型?

我想看看精确的答案是否就像添加在计算器上一样。我可以使用 parseDecimal 或其他数据类型吗?

![在此处输入图片描述][1]

    function SumValues() {
        //debugger;
        var txtSubsContrRbtAmt = document.getElementById("<%=txtSubsContrRbtAmt.ClientID%>");
        var txtDeMinAmt = document.getElementById("<%=txtDeMinAmt.ClientID%>");
        var txtTotRbtAmt = document.getElementById("<%=txtTotRbtAmt.ClientID%>");
        var txtRndRbtAmt = document.getElementById("<%=txtRndRbtAmt.ClientID%>");

        var total = Add(txtSubsContrRbtAmt.value, txtDeMinAmt.value);

        txtTotRbtAmt.value = total;
        txtRndRbtAmt.value = RoundToTwoDecimalPlaces(total);
    }

    function Add() {
        var sum = 0;
        for (var i = 0, j = arguments.length; i < j; i++) {
            var currentValue;
            if (isNumber(arguments[i])) {
                currentValue = parseFloat(arguments[i]);
            }
            else {
                currentValue = 0;
            }

            sum += currentValue;
        }
        return sum;
    }

    function RoundToTwoDecimalPlaces(input) {

        return Math.round(input * 100) / 100
    }

    function IsNumeric(input) {
        return (input - 0) == input && input.length > 0;
    }

    function isNumber(n) {
        return !isNaN(parseFloat(n)) && isFinite(n);
    }

  [1]: http://i.stack.imgur.com/5Otrm.png

更新。我正在评估这样的事情:

function AddWithPrecision(a, b, precision) {
        var x = Math.pow(10, precision || 2);
        return (Math.round(a * x) + Math.round(b * x)) / x;
    }

【问题讨论】:

  • 你期望的结果是什么?
  • 我建议将输入的最大小数位数传递给 .toFixed() 然后从右侧修剪零。
  • 20.013。但如果他们在小数点后输入了更多有效数字,计算的总和也应该包括这些数字。使用 Windows 计算器进行测试。它所显示的,就是我想要的。我惊呆了,这不是一件容易的事。 Javascript 每次都让我失望。
  • 我喜欢你的建议。我也在考虑这些条款。你或有人能帮忙解释一下逻辑吗?这正在推动我的能力......
  • 不是javascript的问题。这是您对浮点数如何工作的误解的问题。在任何其他编程语言中都会得到相同的结果:C、Perl、Ruby 等。编写 Windows 计算器的程序员必须在没有编程语言帮助的情况下进行计算。也就是说,数字存储为数据结构而不是浮点数。

标签: javascript floating-point floating-accuracy


【解决方案1】:

对于任何在金融领域(或任何与金钱打交道的软件)编写软件的人来说,有一条黄金法则:永远不要使用浮点数。因此,大多数处理货币的软件只使用整数并将十进制数表示为数据结构。

这是一种方法:

(注意:这个函数添加了两个看起来像数字的字符串)

(附加说明:没有进行错误检查以帮助清晰。也不处理负数)

function addNumberStrings (a,b) {
    a = a.split('.');
    b = b.split('.');
    var a_decimal = a[1] || '0';
    var b_decimal = b[1] || '0';
    diff = a_decimal.length - b_decimal.length;
    while (diff > 0) {
        b_decimal += '0';
        diff --;
    }
    while (diff < 0) {
        a_decimal += '0';
        diff ++;
    }
    var decimal_position = a_decimal.length;

    a = a[0] + a_decimal;
    b = b[0] + b_decimal;

    var result = (parseInt(a,10)+parseInt(b,10)) + '';

    if (result.length < decimal_position) {
        for (var x=result.length;x<decimal_position;x++) {
            result = '0'+result;
        }
        result = '0.'+result
    }
    else {
        p = result.length-decimal_position;
        result = result.substring(0,p)+'.'+result.substring(p);
    }
    return result;
}

*注意:代码已简化,附加功能作为作业省略。

【讨论】:

    【解决方案2】:

    要以您想要的方式修复您的添加,我建议以某种方式计算每个数字中的小数位 This method, for instance 然后将最大值传递给 toFixed,并修剪任何剩余的零。

    function AddTwo(n1, n2) {
        var n3 = parseFloat(n1) + parseFloat(n2);
        var count1 = Decimals(n1, '.');
        var count2 = Decimals(n2, '.');
        var decimals = Math.max(count1, count2);
        var result = n3.toFixed(decimals)
        var resultDecimals = Decimals(result, '.');
        if (resultDecimals > 0) {
            return result.replace(/\.?0*$/,'');
        }
        else {
            return result;
        }
    }
    
    // Included for reference - I didn't write this
    function Decimals(x, dec_sep)
    {
        var tmp=new String();
        tmp=x;
        if (tmp.indexOf(dec_sep)>-1)
            return tmp.length-tmp.indexOf(dec_sep)-1;
        else
            return 0;
    } 
    

    这是JSFiddle of that

    【讨论】:

      猜你喜欢
      • 2011-11-22
      • 1970-01-01
      • 2018-07-28
      • 1970-01-01
      • 1970-01-01
      • 2015-01-31
      • 2019-01-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多