5

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

循环:

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

功能:

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);
}

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

Iteration  18, float result for x=0.00000000 : 0.000000
Underflow occurred in double_testk!
Iteration  19, float result for x=0.00000000 : 0.000000
Underflow occurred in double_testk!
Iteration  20, float result for x=0.00000000 : 0.000000
Underflow occurred in double_testk!
Iteration  21, float result for x=0.00000000 : 0.000000
Underflow occurred in double_testk!
Invalid exception occurred in double_testk!
Iteration  22, float result for x=0.00000000 : -nan
Underflow occurred in double_testk!
Invalid exception occurred in double_testk!

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

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

4

2 回答 2

6

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

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

只要x至少为 2 -75,就会x * x产生非零结果。它可能在浮点域的次正规部分,精度正在下降,但x•<code>x 的实数结果大到足以舍入到 2 -149或更大。然后,对于这些小x的 ,(1 - cosf(x)) / (x * x)计算结果为零除以非零值,因此结果为零。

x小于 2 −75时,则x * x产生零,因为 •<code>x 的实数结果x非常小,以至于在浮点运算中,它被舍入为零。然后(1 - cosf(x)) / (x * x)计算为零除以零,因此结果为 NaN。这就是您的第 22 次迭代中发生的情况。

(2 -149是 IEEE-754 二进制 32 中可表示的最小正值,您的 C 实现可能将其用于. 与 2 -150float之间的实数结果将四舍五入为 2 -149。较低的结果将四舍五入为 0。假设四舍五入模式是四舍五入到最近,平到偶数。)

于 2020-09-23T16:37:01.173 回答
3

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

1/0 = ∞ //too large     
log (0) = -∞ //too small
sqrt (-1) = NaN //is not a number, can't be calculated

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

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

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

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

FE_UNDERFLOW:较早的浮点运算的结果是不正常的,精度下降。

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

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

如果舍入值的绝对值太大而无法表示,则设置。根据使用的舍入,返回无穷大或最大有限值。

FE_DIVBYZERO: 在较早的浮点运算中发生极点错误。

如果结果是无限给定的有限操作数,则设置,返回无限大,+∞ 或 -∞。

FE_INVALID: 在较早的浮点运算中发生域错误。

设置是否无法返回实值结果,例如 sqrt(-1) 或 0/0,返回安静的 NaN*

*安静的概念NaN

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

资料来源:

浮点环境

浮点运算

20.5.2 无穷大和NaN

于 2020-09-23T16:53:42.663 回答