How to check for NAN / INF / IND in C++

http://studiofreya.com/c/how-to-check-for-nan-inf-ind-in-c/

How to check for NAN / INF / IND in C++

Recently we had occasional, but serious problems with some software we’re making. The problems were with invalid floating point numbers.

Once invalid (IND / INF / NAN) numbers have infested your simulation, it’s very difficult to get rid of it. It’s like a viral infection. The best way to avoid invalid floating point numbers are to prevent them happening in the first place.

What happened was that invalid floating point values were introduced while calculating the angle between two vectors. The acos method calculate the angle, and it’s domain is [-1, 1]. Due to rounding errors, the actual value passed to acos was slightly less or slightly above the domain, which resulted in an invalid number.

The way we caught the error was to modify the vector3d-class and insert breakpoints when the expression value != value is true. Only NAN and IND values behave like that.

After the breakpoints were set, the call stack gave it all away.

Here is a sample program for detecting invalid numbers.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
#include <iostream>     // cout
#include <math.h>       // acos
#include <float.h>      // DBL_MAX
#include <limits>       // numeric_limits
 
template < typename T>
bool is_infinite( const T &value )
{
     // Since we're a template, it's wise to use std::numeric_limits<T>
     //
     // Note: std::numeric_limits<T>::min() behaves like DBL_MIN, and is the smallest absolute value possible.
     //
 
     T max_value = std::numeric_limits<T>::max();
     T min_value = - max_value;
 
     return ! ( min_value <= value && value <= max_value );
}
 
template < typename T>
bool is_nan( const T &value )
{
     // True if NAN
     return value != value;
}
 
template < typename T>
bool is_valid( const T &value )
{
     return ! is_infinite(value) && ! is_nan(value);
}
 
int main()
{
     using std::cout;
 
     double a, b, c, d, e;
 
     a = 1.0;
     b = 0.0;
     c = a / c;          // divide by zero
     d = acos (-1.001);   // domain for acos is [-1, 1], anything else is #IND or inf
     e = b / b;          // zero / zero
 
     cout << "Value of a: " << a << " " << is_valid(a) << " " << (is_nan(a) ? " nan " : "" ) << (is_infinite(a) ? " infinite " : "" ) << "n" ;
     cout << "Value of b: " << b << " " << is_valid(b) << " " << (is_nan(b) ? " nan " : "" ) << (is_infinite(b) ? " infinite " : "" ) << "n" ;
     cout << "Value of c: " << c << " " << is_valid(c) << " " << (is_nan(c) ? " nan " : "" ) << (is_infinite(c) ? " infinite " : "" ) << "n" ;
     cout << "Value of d: " << d << " " << is_valid(d) << " " << (is_nan(d) ? " nan " : "" ) << (is_infinite(d) ? " infinite " : "" ) << "n" ;
     cout << "Value of e: " << e << " " << is_valid(e) << " " << (is_nan(e) ? " nan " : "" ) << (is_infinite(e) ? " infinite " : "" ) << "n" ;
 
     return 0;
}

Output is:

1
2
3
4
5
Value of a: 1 1
Value of b: 0 1
Value of c: inf 0  infinite
Value of d: nan 0  nan  infinite
Value of e: -nan 0  nan  infinite

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值