【问题标题】:Test if a floating point number is an integer in Matlab在Matlab中测试浮点数是否为整数
【发布时间】:2012-10-31 06:57:08
【问题描述】:

我的问题 - 第 1 部分: 测试浮点数是否为“整数”(在 Matlab 中)的最佳方法是什么?

我目前对第 1 部分的解决方案: 显然,isinteger 已经过时了,因为它测试的是元素的类型,而不是值,所以目前,我这样解决问题:

    abs(round(X) - X) <= sqrt(eps(X))

但也许还有更原生的 Matlab 方法?

我的问题 - 第 2 部分: 如果我当前的解决方案确实是最好的方法,那么我想知道是否有推荐的一般公差?从上面可以看出,我使用sqrt(eps(X)),但我真的没有任何好的理由。也许我应该只使用eps(X),或者5 * eps(X)?任何建议都将受到欢迎。

示例: 在 Matlab 中,sqrt(2)^2 == 2 返回 False。但在实践中,我们可能希望该逻辑条件返回 True。使用上述方法可以实现这一点,因为sqrt(2)^2 实际上等于2 + eps(2)(即在sqrt(eps(2)) 的容差范围内。但这是否意味着我应该始终使用eps(X) 作为我的容差,或者有充分的理由要使用更大的容差,例如5 * eps(X),还是sqrt(eps(X))

更新(2012-10-31): @FakeDIY 指出我的问题部分与 this SO question 重复(抱歉,不知道我在最初的搜索中是如何错过的)。鉴于此,我想强调问题的“公差”部分(该链接未涵盖),即eps(X) 是一个合理的公差,还是我应该使用更大的东西,比如5 * eps(X),如果是这样,为什么?

更新(2012-11-01):感谢大家的回复。我已经 +1 了所有三个答案,因为我觉得它们都对问题的各个方面做出了有意义的贡献。我将答案打勾给 Eric Postpischil,因为该答案确实很好地确定了问题的容忍部分(并且它在此时获得了最多的支持)。

【问题讨论】:

标签: matlab floating-point integer


【解决方案1】:

不,没有推荐的一般公差,也不可能。

计算结果和数学理想结果之间的差异是产生计算结果的操作的函数。因为这些操作特定于每个应用程序,所以没有通用规则来测试计算结果的任何属性。

要设计一个合适的测试,您必须确定计算过程中可能发生的错误,确定计算结果中产生的错误的界限,并测试计算结果是否与理想结果(可能是最接近的整数)相差更少比那些界限。您还必须确定这些界限是否足够小以满足您的应用程序的要求。 (使用宽松的测试将非整数的东西作为整数接受会减少假阴性[将结果错误拒绝为整数,而理想结果将是整数],但会增加假阳性[将结果错误接受为整数其中理想的结果不是整数]。)

(请注意,即使错误界限为零的测试也可能会产生假阴性:当理想结果不是整数时,计算产生的结果可能恰好是整数,所以任何容错,即使是零,也会错误地报告这个结果是一个整数。如果这对您的应用程序来说是不可接受的,那么在这种情况下,必须重新设计计算。)

在没有特定应用知识的情况下,不仅不可能说明可以使用的数值公差,而且不可能说明公差应该是绝对的,应该是相对于计算值还是相对于目标值,应以 ULP(最低精度单位)测量,或应以其他方式设置。这是因为错误可能以多种方式引入计算。例如,如果a 的相对误差较小,ab 的值接近,则a-b 的相对误差较大。另外,如果c 很大,那么(a-b)*c 的绝对误差也很大。

【讨论】:

  • +1 每次我想我终于把我的头包裹在浮点算术上,只是为了发现我对这一切知之甚少:)
【解决方案2】:

这可能不是最有效的方法,但我会为此使用mod

a = 15.0000000000;
b = mod(a,1.0)
c = 15.0000000001;
d = mod(c,1.0) 

返回b = 0d = 1.0000e-010

这里建议了许多其他替代方案:

How do I test for integers in MATLAB?

我也喜欢比较 (x == floor(x)) 的想法。

【讨论】:

  • 糟糕,我不太确定在提出问题之前我是如何在搜索中错过了该链接! +1 指出这一点,我将更新问题以改变对容忍问题的重视(无论如何,这正是我真正感兴趣的问题)-您对问题的这方面有什么想法吗?
  • 关于容差,我认为这在很大程度上取决于您的应用程序。出于某些目的,您可能需要高度准确的测试——对于您可能不关心的其他目的。我个人认为 sqrt(abs(X)) 是一个明智的选择。
【解决方案3】:

1) 我过去一直使用您的方法,但有一个简单的容差,eps(X)。不过我对 mod 方法很感兴趣,所以我使用 Steve Eddins timeit 函数对一对夫妇进行了基准测试。

f = @() abs(X - round(X)) <= eps(X);
g = @() X == round(X);
h = @() ~mod(X,1);

对于单个值,例如 X=1.0,您的值似乎最快:

timeit(f) = 7.3635e-006
timeit(g) = 9.9677e-006
timeit(h) = 9.9214e-006

不过,对于向量,例如 X = 1:0.01:100,其他方法更快(尽管 round 仍然优于 mod):

timeit(f) = 0.00076636
timeit(g) = 0.00028182
timeit(h) = 0.00040539

2) 错误界限确实取决于问题。其他答案比我能做到的要好得多。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-10-01
    • 2011-08-13
    • 2013-12-26
    • 2013-11-29
    • 2013-02-25
    • 1970-01-01
    相关资源
    最近更新 更多