比较IEEE浮点数和双精度数据的最佳方法是什么?我听说过几种方法,但我想看看社区的想法.
我认为最好的方法是比较ULP.
bool is_nan(float f) { return (*reinterpret_cast(&f) & 0x7f800000) == 0x7f800000 && (*reinterpret_cast (&f) & 0x007fffff) != 0; } bool is_finite(float f) { return (*reinterpret_cast (&f) & 0x7f800000) != 0x7f800000; } // if this symbol is defined, NaNs are never equal to anything (as is normal in IEEE floating point) // if this symbol is not defined, NaNs are hugely different from regular numbers, but might be equal to each other #define UNEQUAL_NANS 1 // if this symbol is defined, infinites are never equal to finite numbers (as they're unimaginably greater) // if this symbol is not defined, infinities are 1 ULP away from +/- FLT_MAX #define INFINITE_INFINITIES 1 // test whether two IEEE floats are within a specified number of representable values of each other // This depends on the fact that IEEE floats are properly ordered when treated as signed magnitude integers bool equal_float(float lhs, float rhs, unsigned __int32 max_ulp_difference) { #ifdef UNEQUAL_NANS if(is_nan(lhs) || is_nan(rhs)) { return false; } #endif #ifdef INFINITE_INFINITIES if((is_finite(lhs) && !is_finite(rhs)) || (!is_finite(lhs) && is_finite(rhs))) { return false; } #endif signed __int32 left(*reinterpret_cast (&lhs)); // transform signed magnitude ints into 2s complement signed ints if(left < 0) { left = 0x80000000 - left; } signed __int32 right(*reinterpret_cast (&rhs)); // transform signed magnitude ints into 2s complement signed ints if(right < 0) { right = 0x80000000 - right; } if(static_cast (std::abs(left - right)) <= max_ulp_difference) { return true; } return false; }
类似的技术可用于双打.诀窍是转换浮点数以便它们被排序(就像整数一样)然后只看它们有多么不同.
我不知道为什么这个该死的东西搞砸了我的下划线.编辑:哦,也许这只是预览的人工制品.那没关系.