【问题标题】:Purpose of function is unknown, what does it do?功能用途不明,它有什么作用?
【发布时间】:2020-01-11 05:15:03
【问题描述】:

如果输入是复数a+bireal = a, imag = b,有人可以帮我理解这个函数在做什么

我不知道它会计算什么,但也许我遗漏了一些明显的东西?

double function(double real, double imag)
{
  double y;
  double a;
  double b;
  a = fabs(real);
  b = fabs(imag);
  if (a < b) 
  {
    a /= b;
    y = b * sqrt(a * a + 1.0);
  } 
  else if (a > b) 
  {
    b /= a;
    y = a * sqrt(b * b + 1.0);
  } 
  else if (b == NAN) 
  {
    y = b;
  } 
  else 
  {
    y = a * sqrt(2);
  }

  return y;
}

【问题讨论】:

  • 只是abs(),绝对值。 sqrt(real^2 + imag^2)。不清楚为什么会这样混淆。
  • @IgorTandetnik:它没有被混淆。它正在避免溢出。
  • 根据realimag 是否为 NAN,生成函数结果的路径似乎很奇怪(尽管如果a 为 NAN,y = a * sqrt(2); 确实会产生 NAN一个南)。 &lt;math.h&gt; 中还有一个 isnan() 函数。使用它比使用 b == NAN 测试要好,因为 NAN 有多种表示形式。
  • 计算复数值 (real, imag) 的大小并跳过一些简单的循环以避免溢出。
  • @JonathanLeffler 它们是不同的,因为最后一个分支不仅涵盖a == NAN,还涵盖a==b。所以最后两个分支等同于if(b== NAN) {return NAN;} else if(a == NAN) {return NAN;} else { return sqrt(2)*a; /* only is reached for a==b*/},并且这个表示的最后两个分支只是一个。

标签: c++ c function math complex-numbers


【解决方案1】:

该代码尝试计算传递给它的复数的大小(绝对值)而不导致不必要的溢出。

考虑复数a + b i,其中ab是分配给@的值987654321@ 和 b 在函数的前几行。其大小为√(a2+b2)。但是,如果 ab 很大,浮点计算 a*a 可能会溢出浮点格式的有限范围并产生无穷大 (∞),即使幅度在范围内。举个简单的例子,设a为21000b为0,那么大小为√(22000+0) = 21000,但计算 sqrt(a*a + b*b) 会产生无穷大。 (由于a*a 溢出并产生∞,其余计算也产生∞。)

代码尝试通过将 ab 中较小者除以较大者并使用数学上等效但不会溢出的计算来解决此问题。例如,如果a &lt; b 为真,则执行:

a /= b;
y = b * sqrt(a * a + 1.0);

然后a /= b 产生一个小于 1 的值,因此最后一个之前的所有计算都安全地在浮点有限范围内:a * a 小于 1,a * a + 1.0 小于 2,@987654331 @ 小于 1.42。当我们乘以b 时,最终结果可能会溢出到∞。这可能发生的原因有两个: a + b i 的大小可能超出浮点有限范围,因此溢出是正确的。或者先前计算中的舍入可能导致sqrt(a * a + 1.0) 略大于数学结果,并且足以导致b * sqrt(a * a + 1.0) 在幅度的实际值在范围内时溢出。由于这不是我们的重点,因此我不会在此答案中进一步分析此案例。

除了那个四舍五入的问题,前两种情况都很好。但是,这段代码是不正确的:

else if (b == NAN)

根据 IEEE-754 2008 5.11 和 IEEE-754 1985 5.7,NaN 不小于、等于或大于任何操作数,包括它自己。它是无序的。这意味着如果使用 IEEE-754,b == NAN 必须返回 false。 C 2018 不要求使用 IEEE-754,但脚注 22(在 5.2.4.2.2 4)表示,如果不支持 IEC 60559:1989(实际上是 IEEE-754),则术语“安静 NaN”和“信号C 标准中的 NaN”旨在应用于具有类似行为的编码。而 7.12 5 告诉我们 NAN 扩展为代表安静 NaN 的 float。因此,在b == NAN 中,NAN 应该表现为 IEEE-754 NaN,因此b == NAN 应该产生 0,表示 false。

因此,这段由else if (b == NAN) 管理的代码永远不会被执行:

y = b;

相反,执行落入else,它执行:

y = a * sqrt(2);

如果 a 是 NaN,则结果为 NaN,如所愿。但是,如果a 是一个数字而b 是一个NaN,那么当期望的结果是一个NaN 时,这会产生一个数字。因此,代码被破坏了。

【讨论】:

    猜你喜欢
    • 2016-07-17
    • 2012-11-01
    • 1970-01-01
    • 1970-01-01
    • 2014-06-19
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多