Javascript浮点添加解决方法



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

0.23 - 1 + 1 = 0.22999999999999998

由于在javascript中,与其他语言不同,所有的数字实际上都是浮点,并且没有int/decimal,所以有各种各样的库和解决方法,如BigDecimal来处理这个问题。这一点最好在这里讨论。

我正在创建一个支持浮点数字的"数字微调器"控件,很明显,我不希望用户单击"向上"然后单击"向下",得到一个与他开始时不同的数字,所以我尝试编写一个变通方法-某种"addPrecise"方法。

我的想法如下:

  1. 取我要加的两个数字,计算出它们的"精度"——小数点后有多少位数
  2. 将这两个数字作为浮点数相加
  3. 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. 确定小数点后需要多少位数字,例如d
  2. 读取用户的输入,并将其转换为按10d缩放的整数
  3. 用整数做所有算术运算
  4. 为用户显示值时,将其除以10d以进行显示

更多详细信息:

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

只要注意确保算术在合理的范围内完全使用整数(或浮点格式中可以精确表示的其他值),就可以仅使用浮点来实现上述所有操作。

最新更新