Javascript浮点附加解决方法

时间:2013-08-14 08:56:12

标签: javascript floating-point

好的,所以我们都知道浮点数问题,例如:

0.23 - 1 + 1 = 0.22999999999999998

因为在javascript中,与其他语言不同,所有数字实际上都是浮点数并且没有int / decimal,所以有各种库和变通方法(如BigDecimal)来处理这个问题。最好的讨论here

我正在创建一个支持浮点数的“数字微调器”控件,显然我不希望用户点击“向上”然后“向下”并获得与他开始时不同的数字,所以我尝试编写一种解决方法 - 一种“addPrecise”方法。

我的想法如下:

  1. 取两个我要添加的数字,并计算出它们的“精度” - 它们在小数点后的位数。
  2. 将两个数字添加为浮点数
  3. 使用两个
  4. 的最大精度对结果应用toFixed()

    例如:

    float #1: 1.23
    float #2: -1
    

    正常添加它们会产生0.22999999999999998但是如果我取最大小数位数,即#1的2位数,并应用toFixed(2),我得到0.23想要的。

    我用以下代码完成了这项工作,但我对此并不满意。

    function addPrecise(f1, f2){
        var floatRegex = /[^\d\-]/;
        var f1p =  floatRegex.exec(f1.toString()) ? f1.toString().split(floatRegex.exec(f1.toString()))[1].length : 0;
        var f2p =  floatRegex.exec(f2.toString()) ? f2.toString().split(floatRegex.exec(f2.toString()))[1].length : 0;
        var precision = Math.max(f1p,f2p);
        return parseFloat((parseFloat(f1) + parseFloat(f2)).toFixed(precision));
    }
    

    (值得注意的是,我正在使用正则表达式来找到'浮点',因为在其他语言环境中它可能是逗号而不是句号。我也考虑到了我获得Int的可能性(没有意义)在这种情况下它的精度是0。)

    有更干净/更简单/更好的方法吗?

    编辑:我还想指出,找到提取小数位数的可靠方法也是问题的一部分。我不确定那里的方法。

1 个答案:

答案 0 :(得分:1)

针对此问题的合适解决方案是:

  1. 确定小数点后需要多少位数,例如 d
  2. 读取用户的输入并将其转换为按10 d 缩放的整数。
  3. 使用整数进行所有算术运算。
  4. 显示用户的值时,请将它们除以10 d 进行显示。
  5. 更多详情:

    1. 如果所有工作都是用户输入数据的整个单位,那么小数点后面所需的位数 d 与用户接受的位数相同。 (例如,如果要对步长的分数进行一些算术运算,那么可能需要更多的数字。)
    2. 当用户输入输入时,应将其转换为缩放的整数。请注意,用户输入一个字符串(不是浮点数;用户输入时只是一个字符串),字符串应该是数字(表示数字的字符)。处理此输入的一种方法是调用库例程将此数字转换为浮点数,然后乘以10 d ,然后将浮点结果舍入到最接近的整数(以补偿浮点舍入误差)。对于合理大小的数字,这将始终产生完全所需的结果;浮点舍入错误不会成为问题。 (应拒绝过大的用户输入。)处理此输入的另一种方法是编写自己的代码,将数字直接转换为缩放的整数,完全避免浮点。
    3. 只要使用加法,乘法和减法(例如,将步长乘以步数并加上先验值),并且不超过整数范围,则所有算术都是精确的;没有舍入错误。如果使用除法,则必须重新考虑这种方法。
    4. 与读取输入一样,显示输出可以通过浮点和库例程的辅助执行,也可以通过编写自己的代码直接转换来执行。要使用浮点数,请将整数转换为浮点数除以10 d ,并使用库例程将其格式化为不超过 d 位数。 (在库例程中使用默认格式转换可能会导致显示 d 个数字。如果仅显示 d 数字,并且 d 是合理的数字很​​小,然后格式化过程中出现的浮点舍入错误将不可见。)
    5. 可以仅使用浮点实现上述所有操作,只要注意确保算法在合理范围内使用完全整数(或其他可以在浮点格式中精确表示的值)