kjo*_*kjo 3 javascript floating-point precision equality floating-point-precision
我的问题的简要版本是:
怎样才算"最佳实践"的决定时,浮点数
x和Math.round(x)可被视为平等的,允许从浮点运算的精度损失?
啰嗦的版本是:
我经常需要决定给定的浮点值x是否应该被视为"整数",或者更迂腐,应该"被视为整数的浮点表示".
(例如,如果n是整数,则为数学表达式
log 10(10 n)
是一种表示相同整数n的复杂方式.这是一种思维,可以说类似浮点计算的结果可以被视为"整数的表示".)
每当Math.round(x) == x评估时,决策都很容易true:在这种情况下,我们可以说x确实是(整数的浮点表示).
但是Math.round(x) == x当它评估时,测试是不确定的false.例如,
function log10(x) { return Math.log(x)/Math.LN10; }
// -> function()
x = log10(Math.pow(10, -4))
// -> -3.999999999999999
Math.round(x) == x
// -> false
Run Code Online (Sandbox Code Playgroud)
编辑:我经常看到的一个"解决方案"就是选择一些任意的容差? = 1e-6,然后进行测试Math.abs(Math.round(x) - x) < ?.我认为这样的解决方案会产生比我认为更可接受的误报.
正如您在示例中看到的那样x实际上根本不是整数.这是由于计算中较早出现的舍入错误,因此您实际上可能不知道是否将x其定义为几乎是圆整数或圆形数,而是通过舍入误差来加入.
如果你想知道一个或那个是什么数字,你将需要使用你自己建议的限制条件,或者使用足够高的数据,以确保你的数字首先不会出现问题.最后一种方法并不适用于所有情况.
也有象征性地跟踪所有的数学运算,即存储的可能性1/3为1/3,而不是0.3333和评估这些需求抵消,可以像你这样评估由手工表达式时被取消的因素,但这是在几乎所有情况下完全矫枉过正.更不用说这样一个系统会有多复杂.如果这是所需的解决方案,您可以与MatLab或Mathematica或其他东西进行交互来处理评估,除非您在浏览器中运行它,对于浏览器来说可能有点难以尝试WolframAlpha API(为什么我不认为这是第一次?).
尽管如此; 如果您可以通过选择?这样的方式来解决这个问题,那么您将获得满意的结果,这可能是最好的方法.如果静态?不切断它,您可以尝试根据手头数字之前的计算类型动态选择它.即,相乘的数字往往比分割的数字创建的分数部分少,依此类推.如果数字不受加号,减号和乘法(不涉及分数)以外的任何其他因素的影响,您可以知道它最大可以有多少小数位,因此可以选择合理的数字?.