在这种情况下,我如何使用eps来获取累积总和的差异

时间:2016-05-10 23:54:43

标签: matlab double precision

首先,数据:

orig = reshape([0.0000000000000000 0.3480000000000000 0.7570000000000000 1.3009999999999999 2.8300000000000001 4.7519999999999998 5.2660000000000000 5.8120000000000003 14.3360000000000000 15.3390000000000000 ],[10   1])

change = reshape([0.0000000000000000 0.3480000000000000 0.0000000000000000 0.9530000000000000 1.5290000000000001 1.9219999999999997 0.5140000000000002 0.5460000000000003 0.0000000000000000 9.5270000000000010 ],[10   1])

change = cumsum(change)

orig是经过秒数的向量。 change是通过获取orig的(某些)元素之间的差异而得到的向量。 change的累积总和有一些元素实际上等于orig中的对应元素。

但是,由于精度问题:

diff = orig - change

给出

diff =

                         0
                         0
                     0.409
                         0
                         0
                         0
                         0
                         0
                     8.524
     -1.77635683940025e-15

似乎如果我运行以下命令:

diff(abs(diff) <= eps(orig)) = 0

然后将条目设置为零,但不是由于精度问题,为零。

我的问题是,这是正确的方法吗?为什么比较<=而不是<?声明应该是:

diff(abs(diff) < k*eps(orig)) = 0
某些k > 1

给予一些宽容?如果是这样,如何选择k

如果有必要知道change的{​​{1}}是如何派生的,则以下替代示例也会显示此行为:

orig

1 个答案:

答案 0 :(得分:1)

以下陈述只有在“几乎为零”的情况下才会出现,因为1位是非法的。

abs(diff) <= eps(orig)

1位是一个非常高的精度要求,一个你很可能无法实现的精度。通常,您需要自己定义阈值,例如

abs(diff) <= 1e-12 

您还会问如何选择此值。答:我们无法告诉你。它的算法,应用,单位,计算机,具体。

你在计算粒子之间的距离?也许你需要一个更小的容差。你在做经济利润演算?然后1e-12是小数,你肯定不会得到现金。请改用1e-4。或者您使用的算法是否进行数值近似?那你需要更高的容差。您可以使用多少容差,并且将始终是用户选择。

注意:您需要了解用于将此最小阈值设置为正确的类型。 MATLAB使用double作为默认值,但如果您使用其他类型,则此阈值过于严格。作为替代方案,您可以使用

abs(diff) <= 100*eps(class(diff))

如果您的数据类型未修复/已知。