函数的用途未知,它的作用是什么?
Purpose of function is unknown, what does it do?
如果输入是复数 a+bi
和 real = 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;
}
该代码尝试计算传递给它的复数的大小(绝对值)而不会引起不必要的溢出。
考虑复数 a + b i,其中 a 和 b 是函数前几行中分配给 a
和 b
的值。其大小为√(a2+b2 ).但是,如果 a 或 b 很大,浮点计算 a*a
可能会溢出浮点格式的有限范围并产生无穷大 (∞),即使幅度在范围内。举个简单的例子,设a为21000,b为0,则量级为√ (22000+0) = 21000,但计算 sqrt(a*a + b*b)
会产生无穷大。 (由于a*a
溢出产生∞,其余计算也产生∞。)
代码试图通过将 a 和 b 中的较小者除以较大者并使用数学上等效的计算来解决该问题但这不会溢出。例如,如果 a < b
为真,则执行:
a /= b;
y = b * sqrt(a * a + 1.0);
然后a /= b
产生一个小于1的值,所以最后一个之前的所有计算都安全地在浮点有限范围内:a * a
小于1,a * a + 1.0
小于 2,sqrt(a * a + 1.0)
小于 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
必须 return false。 C 2018 不要求使用 IEEE-754,但脚注 22(在 5.2.4.2.2 4)表示,如果不支持 IEC 60559:1989(有效的 IEEE-754),术语“quiet NaN”和C 标准中的“信号 NaN”旨在应用于具有类似行为的编码。 7.12 5 告诉我们 NAN
扩展为 float
表示一个安静的 NaN。因此,在 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 时,这会产生一个数字作为结果。因此,代码被破坏了。
如果输入是复数 a+bi
和 real = 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;
}
该代码尝试计算传递给它的复数的大小(绝对值)而不会引起不必要的溢出。
考虑复数 a + b i,其中 a 和 b 是函数前几行中分配给 a
和 b
的值。其大小为√(a2+b2 ).但是,如果 a 或 b 很大,浮点计算 a*a
可能会溢出浮点格式的有限范围并产生无穷大 (∞),即使幅度在范围内。举个简单的例子,设a为21000,b为0,则量级为√ (22000+0) = 21000,但计算 sqrt(a*a + b*b)
会产生无穷大。 (由于a*a
溢出产生∞,其余计算也产生∞。)
代码试图通过将 a 和 b 中的较小者除以较大者并使用数学上等效的计算来解决该问题但这不会溢出。例如,如果 a < b
为真,则执行:
a /= b;
y = b * sqrt(a * a + 1.0);
然后a /= b
产生一个小于1的值,所以最后一个之前的所有计算都安全地在浮点有限范围内:a * a
小于1,a * a + 1.0
小于 2,sqrt(a * a + 1.0)
小于 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
必须 return false。 C 2018 不要求使用 IEEE-754,但脚注 22(在 5.2.4.2.2 4)表示,如果不支持 IEC 60559:1989(有效的 IEEE-754),术语“quiet NaN”和C 标准中的“信号 NaN”旨在应用于具有类似行为的编码。 7.12 5 告诉我们 NAN
扩展为 float
表示一个安静的 NaN。因此,在 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 时,这会产生一个数字作为结果。因此,代码被破坏了。