C中下溢和nan有什么区别?

Tim*_*Tim 5 c floating-point computer-science loops sigfpe

目前我正在学习浮点异常。我正在写一个带有函数的循环。在该函数中,计算出的值等于0.5。随着循环的进行,输入值除以10

循环:

 for(i = 0; i < e; i++)
 {
     xf /= 10.0;   // force increasingly smaller values for x
     float_testk (xf, i);
 }
Run Code Online (Sandbox Code Playgroud)

功能:

void float_testk(float x, int i)
{
    float result;
   
    feclearexcept(FE_ALL_EXCEPT); // clear all pending exceptions
         
    result = (1 - cosf(x)) / (x * x);
        
    if(fetestexcept(FE_UNDERFLOW) != 0)
        fprintf(stderr,"Underflow occurred in double_testk!\n");
    if(fetestexcept(FE_OVERFLOW) != 0)
        fprintf(stderr,"Overflow occurred in double_testk!\n");
    if(fetestexcept(FE_INVALID) != 0)
        fprintf(stderr,"Invalid exception occurred in double_testk!\n");
   
    printf("Iteration %3d, float result for x=%.8f : %f\n",i,x,result);
}
Run Code Online (Sandbox Code Playgroud)

前几次迭代输出是左右0.5,后来它变成了0CC。过了一会儿,这是程序的输出:

 for(i = 0; i < e; i++)
 {
     xf /= 10.0;   // force increasingly smaller values for x
     float_testk (xf, i);
 }
Run Code Online (Sandbox Code Playgroud)

我想知道从下溢到NaN. 因为下溢意味着数字太小,无法存储在内存中。

但是如果数量已经太少了,那么目标是NaN什么?

Eri*_*hil 6

因为下溢意味着数字太小,无法存储在内存中。

不完全的; 在浮点中,下溢意味着结果低于可以全精度表示数字的范围。结果可能仍然相当准确。

只要x至少为 2 ?75,就会x * x产生非零结果。这可能是在浮点域,其中精度下降的部分低于正常,但实数结果xx足够大到轮2 ?149或更高。然后,对于这些小x,(1 - cosf(x)) / (x * x)计算为零除以非零值,因此结果为零。

x小于2 ?75,然后x * x产生零,因为实数结果xx是如此之小,在浮点运算,它被四舍五入为零。然后(1 - cosf(x)) / (x * x)计算为零除以零,因此结果是 NaN。这就是您的迭代 22 中发生的情况。

(2 ?149是 IEEE-754 binary32 中可表示的最小正值,您的 C 实现可能将其用于float。在 2 ?150和 2 ?150之间的实数结果将向上舍入为 2 ?149。较低的结果将向下舍入为 0。假设舍入模式是舍入到最近的,并列到偶数。)


ana*_*ciu 3

NaN是 IEEE 754 标准中定义的浮点运算概念,不是数字,与负无穷或正无穷不同,NaN用于无法表示的算术值,不是因为它们太小或太大,而是简单因为它们不存在。例子:

\n
1/0 = \xe2\x88\x9e //too large     \nlog (0) = -\xe2\x88\x9e //too small\nsqrt (-1) = NaN //is not a number, can\'t be calculated\n
Run Code Online (Sandbox Code Playgroud)\n
\n

IEEE 754 浮点数可以表示正无穷大或负无穷大以及 NaN(不是数字)。这三个值是由结果未定义或无法准确表示的计算产生的。您还可以特意为其中任何一个设置浮点变量,这有时很有用。产生无穷大或 NaN 的一些计算示例:

\n
\n

您使用这些标志的目的是符合上述标准。它指定了要记录在状态标志中的五个算术异常:

\n

FE_INEXACT:结果不精确,需要舍入才能存储早期浮点运算的结果。

\n
\n

如果舍入(和返回)值与运算的数学精确结果不同,则设置。

\n
\n

FE_UNDERFLOW:早期浮点运算的结果不正常,并且有精度损失。

\n
\n

如果舍入值很小(如 IEEE 754 中指定)且不精确(或者可能仅限于它具有非规范化损失,如 IEEE 754 的 1984 版本),则设置,返回包含零的次正规值。

\n
\n

FE_OVERFLOW:早期浮点运算的结果太大而无法表示。

\n
\n

如果四舍五入值的绝对值太大而无法表示,则设置。返回无穷大或最大有限值,具体取决于使用的舍入方式。

\n
\n

FE_DIVBYZERO:早期浮点运算中发生极点错误。

\n
\n

如果给定有限操作数结果为无限,则设置,返回无穷大,即 +\xe2\x88\x9e 或 \xe2\x88\x92\xe2\x88\x9e。

\n
\n

FE_INVALID:早期浮点运算中发生域错误。

\n
\n

如果无法返回实值结果,例如 sqrt(\xe2\x88\x921) 或 0/0,则设置,返回安静的 NaN*

\n
\n

*安静的概念NaN

\n
\n

安静的 NaN 或 qNaN 在大多数操作中传播时不会引发任何其他异常。例外情况是 NaN 不能简单地原封不动地传递到输出,例如在格式转换或某些比较操作中。

\n
\n

资料来源:

\n

浮点环境

\n

浮点运算

\n

20.5.2 无穷大和 NaN

\n

\n