【问题标题】:How to check if Math.cos(angle) = 0如何检查 Math.cos(angle) = 0
【发布时间】:2015-05-03 02:09:14
【问题描述】:

我正在尝试为tan 函数找到正确的域,我知道

tan x = sinx / cos x

cos x = 0 时,tan 未定义。所以

我正在尝试检查 cos x 是否为 0。

 if ( Math.Cos(x).Equals(0) )
 {
     // do stuff
 }

但这绝不是真的,因为 Math.Cos 返回 6.123....E-17 如何检查 cos == 0 ?

【问题讨论】:

  • 由于这里使用的是双精度,你应该添加一个合理的误差范围。
  • 奇怪的是,以前没有人尝试过比较双打...bing.com/search?q=C%23+double+compare 似乎正在产生一些结果 - 可能这不是第一次...
  • 只有当参数恰好为 +/- pi/2 时,它才恰好为 0。从来都不是,浮点数没有足够的精度。
  • 为什么不检查 x 的值以确保它与 pi/2 + kpi 不同?
  • @FDL 我想过这个,但不知道如何进行检查。

标签: c#


【解决方案1】:

您需要稍微扩大您的期望 - 为了使 Math.Cos(x) 真正等于 0,您要么需要 Cos 不准确(当然会发生这种情况),要么让 x 有一个不合理的值。

相反,您应该计算出一些公差 - Math.Cos 的某个值范围非常接近 到 0。例如:

if (Math.Abs(Math.Cos(x)) < 1e-15)

1e-15 的选择非常随意——你应该为你的特定任务确定你想要它是什么。 (当然,这仍然会提供相当大的 tan 值......)

【讨论】:

  • double.Epsilon怎么样?
  • double.Epsilon 太小了。
  • double.Epsilon 不是用于模糊比较的 epsilon,而是可以用双精度浮点数表示的不为零的最小值。
  • 值得注意的是,通常这些阈值(即:1e-15)通常取决于后续计算的性质。在某些情况下(多重导数等),您实际上必须比其他情况更早地截断,以避免数字在后续计算中爆炸。您的整个系统将有一个“通常可计算的”域,您通常必须弄清楚每种情况下的情况。
【解决方案2】:

如果您的问题是收到来自Math.Tan 的异常,Math.Tan 不会抛出。它唯一能做的就是返回Double.NaN 和(也许)Double.PositiveInfinity/Double.NegativeInfinity,所以只需检查它们:

double t = Math.Tan(something);

if (!double.IsInfinity(t) && !double.IsNaN(t))
{
    // Do Something
}

【讨论】:

    【解决方案3】:

    问题是您需要不直接比较它,而是需要一定的准确度,因为浮点值是如何在内存中表示的。

    您可以使用以下代码来修复它:

    const double Epsilon = 0.0001;
    
    if (Math.Cos(x) < Epsilon)
    {
        // Code here
    }
    

    此外,编写 Math.Cos(x).Equals(something) 也没有意义,因为它使代码更难阅读。

    如果您想了解更多关于为什么您的代码无法运行的信息,您可以在此处查看:http://www.parashift.com/c++-faq/floating-point-arith.html

    这是 C++ 的常见问题解答,但同样适用于您的情况。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2012-11-01
      • 2022-12-02
      • 2017-04-05
      • 2021-02-11
      • 1970-01-01
      • 1970-01-01
      • 2019-10-16
      • 1970-01-01
      相关资源
      最近更新 更多