在一系列浮点运算后,是否存在“最佳实践”与浮点数的相等比较?
我在R中有以下示例,但问题不仅适用于R而且适用于使用浮点的任何语言。我有一个双x = 1
,我应用了一系列的加法和减法。最后x
应该只是一个但不是浮点运算(来自我收集的)。这是示例
> stop_times <- seq(0.25, 2, by = .25)
> expr <- expression(replicate(100,{
+ x <- 1
+
+ for(i in 1:10){
+ tmp <- rexp(1, 1)
+ n <- sample.int(1e2, 1)
+ delta <- tmp / n
+ for(j in 1:n)
+ x <- x - delta
+ x <- x + tmp
+ }
+
+ # "correct" answer is 4
+ which.max(x <= stop_times)
+ }))
> eval(expr)
[1] 5 5 5 4 4 4 5 5 5 4 5 4 4 4 5 5 4 4 5 4 5 4 5 4 5 5 5 4 4 4 4 4 4 4 4 4 5 5 5 5 5 4 5 4 5 5 5 4 4 5 5 5 4 4 5 5 5 4 4 4 4 4 4
[64] 5 4 4 4 5 5 5 4 4 4 5 4 4 4 4 4 4 4 4 5 5 5 5 4 4 4 5 5 5 5 5 4 4 4 5 5 4
一个(天真的?)解决方案是在不等式的右边添加一些任意小的正数,如下所示
some_arbitrary_factor <- 100
stop_times <- seq(0.25, 2, by = .25) +
some_arbitrary_factor * .Machine$double.eps
eval(expr)
[1] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
[64] 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4 4
这是“最佳做法”吗?如果有的话,是否有关于如何选择some_arbitrary_factor
的指南?
我的具体问题是我有时间段$(t_0,t_1),(t_1,t_2),\ dots $并且需要在给定观察$ x $所在的时间段内找出。$ x $可能有在经历了一系列浮点算术运算之后被设置为一个边界$ t_i $,如果执行了精确的操作,则应该导致$ t_i $。
答案 0 :(得分:5)
不,没有最好的做法。不幸的是,没有,因为几乎所有的浮点计算都会引入一些舍入误差,并且错误的后果对于不同的应用程序是不同的。
通常,软件会执行一些计算,理想情况下会产生一些精确的数学结果 x 但是,由于舍入误差(或其他问题),产生近似值 x & #39 ;.比较浮点数时,您想询问一些关于 x 的问题,例如“Is x &lt; 1?“或” x = 3.1415926 ......?“所以你要解决的问题是”我如何使用 x &#39;回答关于 x 的问题?“
对此没有通用的解决方案。某些错误可能会产生 x &#39;即使 x 小于1,也会大于1.某些错误可能会产生 x &#39;即使x大于1,小于1也是如此。任何特定实例中的解决方案都取决于计算 x &#39;时生成的错误的信息。以及要回答的具体问题。
有时,彻底的分析可以证明可以使用 x &#39;来回答有关 x 的某些问题。例如,在某些情况下,我们可能会进行计算,以便我们知道,如果 x &#39; &LT; 1,然后 x &lt;或者,如果 x &#39; &LT; .99875,然后 x &lt; 1.假设我们分析了用于计算 x &#39;的计算。并且可以显示最终错误小于.00125。然后,如果 x &#39; &LT; .99875,然后我们知道 x &lt; 1,如果 x &#39; &GT; 1.00125,然后 x &gt;但是,如果.99875&lt; X &#39; &LT; 1.00125,那么我们不知道 x &gt; 1或 x &lt; 1.在那种情况下我们该怎么做?然后,您的应用程序更好地选择 x &lt; 1或 x &gt;的路径1?答案是针对每个应用程序的,并且没有一般的最佳实践。
我将补充一点,发生的舍入错误量因应用程序而异。这是因为舍入误差可以以各种方式复合。一些具有少量浮点运算的应用程序将获得具有小错误的结果。一些具有许多浮点运算的应用程序也将获得具有适度错误的结果。但某些行为会导致计算误入歧途并产生灾难性错误。因此,处理舍入误差是每个程序的自定义问题。