研究浮点异常总结:
首先看下glibc里面给出的用例,从这里去理解arm手册(毕竟手册那么厚又是english)里描述的几种浮点异常到底是怎么回事
- FE_INVALID 无效操作异常 测试用例是0.0/0.0,还有-1开平方根也是
- FE_DIVBYZERO 除0异常,很好理解,测试用例是1.0/0.0
- FE_OVERFLOW 上溢出操作异常 测试用例是FLT_MAX+1.0e32f,好理解
- FE_UNDERFLOW 下溢出操作异常 测试用例是FLT_MIN/3.0,可以理解
- FE_INEXACT 测试用例是2.0/3.0=0.6666666…,意思是得到的是无限循环小数
Tripping floating-point exceptions
Floating-point exceptions are, as you might expect by virtue of the name, rare. The ones that happen most commonly by mistake in my experience are the zero-divide and invalid operation exceptions. Zero divide tends to happen whenever you have an unchecked normalization operation, such as resetting a 2D or 3D vector to unit length — which works fine, until someone hands you a vector of length zero. Another example would be trying to normalize a portion of audio that was totally silent. When the zero-divide exception is masked, the FPU spits out a signed infinity instead, which sometimes works out in the end. For instance, if the expression is of the form |x/y| > n, then the infinity would give you the correct result.
Invalid operation exceptions are more serious and result from operations that don’t have a graceful way to degrade, such as 0/0, the square root of -1, etc. These too often result from the lack of bounds checks. For instance, a common way to determine the angle between two vectors is through dot product, since the shortest angle between two vectors is acos(dot(v1 / |v1|, v2 / |v2|)). Unfortunately, the common way of normalizing vectors is to multiply by the reciprocal square root of the squared length (dot(v,v)), which can give you a not-quite-unit-length vector since the squaring operation discards half of the usual precision. This can then lead to taking the arccosine of a number slightly larger than 1. When such an operation occurs and invalid operation exceptions are masked, the FPU spits out a Not a Number (NaN) value and keeps going. You can also trip such an exception by trying to operate on NaNs, especially by loading garbage data that isn’t a valid IEEE finite number.
In general, you don’t want to be tripping floating-point exceptions, even if they are masked. The reason is that when the FPU hits one, the fast hardware can’t handle it and punts to the microcode, which then takes about twenty times longer. This is especially bad with NaNs since any operation with a NaN produces another NaN, causing them to spread throughout your calculations (NaN disease) and slow down everything massively. You can even crash due to NaNs blowing past clamp expressions, since any comparison with a NaN is false and converting one to integer form results in integer indefinite (0x80000000). Despite the erroneous results, though, NaNs can appear sporadically in a large Win32 program without anyone knowing, and may go unnoticed in a code base for years.
Note that although exceptions are really slow and usually indicate mistakes, the results when the exceptions are masked are well-defined. It is possible, and sometimes reasonable, to actually depend on and test for specific results from masked exceptions. So it isn’t valid to simply say “don’t do that.”
————————————————
版权声明:本文为CSDN博主「lhh95808」的原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/lhh95808/article/details/447990
PS:glibc里面找到的FLT_MAX和FLT_MIN的描述