比较IEEE浮动和双打的平等 [英] Comparing IEEE floats and doubles for equality

查看:236
本文介绍了比较IEEE浮动和双打的平等的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

比较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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆