Currently I'm learning about floating point exceptions. I'm writing a loop with a function. In that function a value is calculated that equals 0.5
. As the loop proceeds, the input value gets divided by 10
.
The loop:
for(i = 0; i < e; i++)
{
xf /= 10.0; // force increasingly smaller values for x
float_testk (xf, i);
}
The function:
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);
}
The first few iterations the output is around 0.5
and later it becomes 0
due CC. After a while this is the output of the program:
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!
I want to know what happens at the transition from underflow to NaN
. Because underflow means that the number is too small to be stored in the memory.
But if the number is already too small, what is the goal of NaN
?
NaN
is a concept defined in IEEE 754 standard for floating-point arithmetic, not being a number is not the same as negative infinity or positive infinity,NaN
is used for arithmetic values that cannot be represented, not because they are too small or too large but simply because they don't exist. Examples:The goal of these flags you are using is to be compiant with the mentioned standard. It specifies five arithmetic exceptions that are to be recorded in the status flags:
FE_INEXACT
: Inexact result, rounding was necessary to store the result of an earlier floating-point operation.FE_UNDERFLOW
: The result of an earlier floating-point operation was subnormal with a loss of precision.FE_OVERFLOW
: The result of an earlier floating-point operation was too large to be representable.FE_DIVBYZERO
: Pole error occurred in an earlier floating-point operation.FE_INVALID
: Domain error occurred in an earlier floating-point operation.*Concept of quiet
NaN
:Sources:
Floating point environment
Floating-point arithmetic
20.5.2 Infinity and NaN
NaN