比较IEEE浮动和双打的平等 [英] Comparing IEEE floats and doubles for equality
本文介绍了比较IEEE浮动和双打的平等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!
问题描述
我认为最好的方法是比较 ULP 。
< $ c $ b bool is_nan(float f)
{
return(* reinterpret_cast&unsigned __int32 *>(& f)& 0x7f800000)== 0x7f800000&& (* reinterpret_cast< unsigned __int32 *>(& f)& 0x007fffff)!= 0;
bool is_finite(float f)
{
return(* reinterpret_cast&unsigned __int32 *>(& f)& 0x7f800000)!= 0x7f800000 ;
}
//如果定义了这个符号,那么NaN永远不会等于任何东西(如在IEEE浮点中是正常的)
//如果这个符号没有被定义,NaNs与常规数字大不相同,但可能相等。
#define UNEQUAL_NANS 1
//如果定义了这个符号,infinites永远不会等于有限数字(因为它们难以想象地大)
//如果这个符号没有定义,infinities是1 ULP远离+/- FLT_MAX
#define INFINITE_INFINITIES 1
//测试两个IEEE浮点数是否在指定的数字相互之间的可表示值
//这取决于IEEE浮点数在处理为有符号数量整数时正确排序的事实
bool equal_float(float lhs,float rhs,unsigned __int32 max_ulp_difference)
{
#ifdef UNEQUAL_NANS
if(is_nan(lhs)|| is_nan(rhs))
{
return false; ((is_finite(lhs)&!is_finite(rhs))||(!is_finite(lhs)&& amp; amp; amp; ; is_finite(rhs)))
{
return false;
}
#endif
signed __int32 left(* reinterpret_cast< signed __int32 *>(& lhs));
//将带符号的数值整型转换为2s补码signed int
if(left <0)
{
left = 0x80000000 - left;
}
signed __int32 right(* reinterpret_cast< signed __int32 *>(& rhs));
//将带符号的数值变换成2s补码signed int
if(right< 0)
{
right = 0x80000000 - right;
if(static_cast< unsigned __int32>(std :: abs(left - right))< = max_ulp_difference)
{
return true;
}
返回false;
$ b类似的技术可以用于双打。诀窍是转换浮动,使他们有序(就像整数),然后只是看看他们是多么不同。
我不知道为什么这个该死的东西正在搞砸我的下划线。编辑:哦,也许这只是预览的人造物。那就好了。
What is the best method for comparing IEEE floats and doubles for equality? I have heard of several methods, but I wanted to see what the community thought.
解决方案The best approach I think is to compare ULPs.
bool is_nan(float f) { return (*reinterpret_cast<unsigned __int32*>(&f) & 0x7f800000) == 0x7f800000 && (*reinterpret_cast<unsigned __int32*>(&f) & 0x007fffff) != 0; } bool is_finite(float f) { return (*reinterpret_cast<unsigned __int32*>(&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<signed __int32*>(&lhs)); // transform signed magnitude ints into 2s complement signed ints if(left < 0) { left = 0x80000000 - left; } signed __int32 right(*reinterpret_cast<signed __int32*>(&rhs)); // transform signed magnitude ints into 2s complement signed ints if(right < 0) { right = 0x80000000 - right; } if(static_cast<unsigned __int32>(std::abs(left - right)) <= max_ulp_difference) { return true; } return false; }
A similar technique can be used for doubles. The trick is to convert the floats so that they're ordered (as if integers) and then just see how different they are.
I have no idea why this damn thing is screwing up my underscores. Edit: Oh, perhaps that is just an artefact of the preview. That's OK then.
这篇关于比较IEEE浮动和双打的平等的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!
查看全文