C++源码分享(一):浮点数比较类

本文介绍了一种浮点数比较的方法,包括等于、不等于、小于、大于等比较操作,并通过特化处理浮点数的精度问题。文章还提供了一个测试函数来验证比较方法的有效性。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

  浮点数比较是常见应用程序特别是矢量图形类数据常见的需要,使用方法参见测试函数

 

//**********************************************************************
// Copyright (c) 2010
// 迪斯特软件开发小组.
// 文件: FloatCompare.hpp
// 内容: 浮点数比较类
// 历史:
//    序号        修改时间        修改人        修改内容
//    1            2010-7-21          hlq              首次生成
//*********************************************************************

//声明本头文件宏   
#ifndef _FLOATCOMPARE_HPP
#define _FLOATCOMPARE_HPP

//包含头文件
#include <cassert>

////////////////////////////////////////////////// 浮点数精度特征 ///////////////////////////////////////////////////

//**********************************************************************
// 类名: EPSTraits
// 目的: 容许误差特征类
//*********************************************************************
template<typename T>
struct EPSTraits
{
    typedef T                                                    value_type;
};

//**********************************************************************
// 类名: EPSTraits
// 目的: 容许误差特征类(浮点数特化)
//*********************************************************************
template<>
struct EPSTraits<float>
{
    typedef float                                                value_type;
    enum{precision = 10000};
};

//**********************************************************************
// 类名: EPSTraits
// 目的: 容许误差特征类(浮点数特化)
//*********************************************************************
template<>
struct EPSTraits<double>
{
    typedef double                                                value_type;
    enum{precision = 10000};
};

////////////////////////////////////////////////// 不等于比较 ///////////////////////////////////////////////////

//**********************************************************************
// 函数: Unequal
// 功能: 不相等比较
//*********************************************************************
template <typename T,typename U>
inline bool Unequal(const T& a,const U& b)
{
    return a != b;
}

//**********************************************************************
// 函数: Unequal
// 功能: 不相等比较(单精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool Unequal(const T& a,float b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return (a < (b - dEPS)) || (a > (b + dEPS));
}

//**********************************************************************
// 函数: Unequal
// 功能: 不相等比较(单精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool Unequal(float a,const U& b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return Unequal(b,a,dEPS);
}

//**********************************************************************
// 函数: Unequal
// 功能: 不相等比较(单精度浮点数特化)
//*********************************************************************
inline bool Unequal(float a,float b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return (a < (b - dEPS)) || (a > (b + dEPS));
}

//**********************************************************************
// 函数: Unequal
// 功能: 不相等比较(双精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool Unequal(const T& a,double b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return (a < (b - dEPS)) || (a > (b + dEPS));
}

//**********************************************************************
// 函数: Unequal
// 功能: 不相等比较(双精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool Unequal(double a,const U& b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return Unequal(b,a,dEPS);
}

//**********************************************************************
// 函数: Unequal
// 功能: 不相等比较(单精度浮点数特化)
//*********************************************************************
inline bool Unequal(double a,double b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return (a < (b - dEPS)) || (a > (b + dEPS));
}

////////////////////////////////////////////////// 等于比较 ///////////////////////////////////////////////////

//**********************************************************************
// 函数: Equal
// 功能: 相等比较
//*********************************************************************
template <typename T,typename U>
inline bool Equal(const T& a,const U& b)
{
    return a == b;
}

//**********************************************************************
// 函数: Equal
// 功能: 相等比较(单精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool Equal(const T& a,float b,float dEPS = 1.0f / EPSTraits<float>::precision)
{
    return !Unequal(a,b,dEPS);
}

//**********************************************************************
// 函数: Equal
// 功能: 相等比较(单精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool Equal(float a,const U& b,float dEPS = 1.0f / EPSTraits<float>::precision)
{
    return !Unequal(a,b,dEPS);
}

//**********************************************************************
// 函数: Equal
// 功能: 相等比较(单精度浮点数特化)
//*********************************************************************
inline bool Equal(float a,float b,float dEPS = 1.0f / EPSTraits<float>::precision)
{
    return !Unequal(a,b,dEPS);
}

//**********************************************************************
// 函数: Equal
// 功能: 相等比较(双精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool Equal(const T& a,double b,double dEPS = 1.0f / EPSTraits<double>::precision)
{
    return !Unequal(a,b,dEPS);
}

//**********************************************************************
// 函数: Equal
// 功能: 相等比较(双精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool Equal(double a,const U& b,double dEPS = 1.0f / EPSTraits<double>::precision)
{
    return !Unequal(a,b,dEPS);
}

//**********************************************************************
// 函数: Equal
// 功能: 相等比较(单精度浮点数特化)
//*********************************************************************
inline bool Equal(double a,double b,double dEPS = 1.0f / EPSTraits<double>::precision)
{
    return !Unequal(a,b,dEPS);
}

////////////////////////////////////////////////// 小于比较 ///////////////////////////////////////////////////

//**********************************************************************
// 函数: Less
// 功能: 小于比较
//*********************************************************************
template <typename T,typename U>
inline bool Less(const T& a,const U& b)
{
    return a < b;
}

//**********************************************************************
// 函数: Less
// 功能: 小于比较(单精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool Less(const T& a,float b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return a < (b - dEPS);
}

//**********************************************************************
// 函数: Less
// 功能: 小于比较(单精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool Less(float a,const U& b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return (a + dEPS) < b;
}

//**********************************************************************
// 函数: Less
// 功能: 小于比较(单精度浮点数特化)
//*********************************************************************
inline bool Less(float a,float b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return a < (b - dEPS);
}

//**********************************************************************
// 函数: Less
// 功能: 小于比较(双精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool Less(const T& a,double b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return a < (b - dEPS);
}

//**********************************************************************
// 函数: Less
// 功能: 小于比较(双精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool Less(double a,const U& b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return (a + dEPS) < b;
}

//**********************************************************************
// 函数: Less
// 功能: 小于比较(单精度浮点数特化)
//*********************************************************************
inline bool Less(double a,double b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return a < (b - dEPS);
}

////////////////////////////////////////////////// 大于比较 ///////////////////////////////////////////////////

//**********************************************************************
// 函数: Great
// 功能: 大于比较
//*********************************************************************
template <typename T,typename U>
inline bool Great(const T& a,const U& b)
{
    return a > b;
}

//**********************************************************************
// 函数: Great
// 功能: 大于比较(单精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool Great(const T& a,float b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return a > (b + dEPS);
}

//**********************************************************************
// 函数: Great
// 功能: 大于比较(单精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool Great(float a,const U& b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return (a - dEPS) > b;
}

//**********************************************************************
// 函数: Great
// 功能: 大于比较(单精度浮点数特化)
//*********************************************************************
inline bool Great(float a,float b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return a > (b + dEPS);
}

//**********************************************************************
// 函数: Great
// 功能: 大于比较(双精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool Great(const T& a,double b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return a > (b + dEPS);
}

//**********************************************************************
// 函数: Great
// 功能: 大于比较(双精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool Great(double a,const U& b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return (a - dEPS) > b;
}

//**********************************************************************
// 函数: Great
// 功能: 大于比较(单精度浮点数特化)
//*********************************************************************
inline bool Great(double a,double b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return a > (b + dEPS);
}

////////////////////////////////////////////////// 小于等于比较 ///////////////////////////////////////////////////

//**********************************************************************
// 函数: LessEqual
// 功能: 小于等于比较
//*********************************************************************
template <typename T,typename U>
inline bool LessEqual(const T& a,const U& b)
{
    return a <= b;
}

//**********************************************************************
// 函数: LessEqual
// 功能: 小于等于比较(单精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool LessEqual(const T& a,float b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return !Great(a,b,dEPS);
}

//**********************************************************************
// 函数: LessEqual
// 功能: 小于等于比较(单精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool LessEqual(float a,const U& b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return !Great(a,b,dEPS);
}

//**********************************************************************
// 函数: LessEqual
// 功能: 小于等于比较(单精度浮点数特化)
//*********************************************************************
inline bool LessEqual(float a,float b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return !Great(a,b,dEPS);
}

//**********************************************************************
// 函数: LessEqual
// 功能: 小于等于比较(双精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool LessEqual(const T& a,double b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return !Great(a,b,dEPS);
}

//**********************************************************************
// 函数: LessEqual
// 功能: 小于等于比较(双精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool LessEqual(double a,const U& b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return !Great(a,b,dEPS);
}

//**********************************************************************
// 函数: LessEqual
// 功能: 小于等于比较(单精度浮点数特化)
//*********************************************************************
inline bool LessEqual(double a,double b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return !Great(a,b,dEPS);
}

////////////////////////////////////////////////// 大于等于比较 ///////////////////////////////////////////////////

//**********************************************************************
// 函数: GreatEqual
// 功能: 大于等于比较
//*********************************************************************
template <typename T,typename U>
inline bool GreatEqual(const T& a,const U& b)
{
    return a >= b;
}

//**********************************************************************
// 函数: GreatEqual
// 功能: 大于等于比较(单精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool GreatEqual(const T& a,float b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return !Less(a,b,dEPS);
}

//**********************************************************************
// 函数: GreatEqual
// 功能: 大于等于比较(单精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool GreatEqual(float a,const U& b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return !Less(a,b,dEPS);
}

//**********************************************************************
// 函数: GreatEqual
// 功能: 大于等于比较(单精度浮点数特化)
//*********************************************************************
inline bool GreatEqual(float a,float b,float dEPS =  1.0f / EPSTraits<float>::precision)
{
    return !Less(a,b,dEPS);
}

//**********************************************************************
// 函数: GreatEqual
// 功能: 大于等于比较(双精度浮点数特化)
//*********************************************************************
template <typename T>
inline bool GreatEqual(const T& a,double b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return !Less(a,b,dEPS);
}

//**********************************************************************
// 函数: GreatEqual
// 功能: 大于等于比较(双精度浮点数特化)
//*********************************************************************
template <typename U>
inline bool GreatEqual(double a,const U& b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return !Less(a,b,dEPS);
}

//**********************************************************************
// 函数: GreatEqual
// 功能: 大于等于比较(单精度浮点数特化)
//*********************************************************************
inline bool GreatEqual(double a,double b,double dEPS =  1.0f / EPSTraits<double>::precision)
{
    return !Less(a,b,dEPS);
}

//**********************************************************************
// 函数: FloatCompare_Test
// 功能: 浮点数比较测试
//*********************************************************************
template<typename DummyType>
inline void FloatCompare_Test(void)
{
    //测试用例1: 等于测试
    int nValue = 3;
    float dEPS = 1.0f / EPSTraits<float>::precision;
    float dEPS_Half = dEPS / 2;
    float dEPS_Double = dEPS * 2;
    float dEPS_Third = dEPS * 3;
    assert(Equal(nValue,nValue));
    assert(Equal(nValue,nValue + dEPS_Half));
    assert(Equal(nValue + dEPS_Half,nValue + dEPS_Half));
    assert(Equal(nValue + dEPS_Half , nValue));
    assert(!Equal(nValue,nValue + dEPS_Double));
    assert(!Equal(nValue + dEPS_Double,nValue));
    assert(Equal(nValue + dEPS_Double,nValue,dEPS_Third));
    assert(Equal(nValue,nValue + dEPS_Double,dEPS_Third));
    assert(!Equal(nValue + dEPS_Double * 2,nValue,dEPS_Third));
    assert(!Equal(nValue,nValue + dEPS_Double * 2,dEPS_Third));

    //测试用例2: 不等于测试
    int nValue2 = nValue + 1;
    assert(Unequal(nValue,nValue2));
    assert(!Unequal(nValue,nValue + dEPS_Half));
    assert(!Unequal(nValue + dEPS_Half , nValue));
    assert(!Unequal(nValue + dEPS_Half,nValue + dEPS_Half));
    assert(Unequal(nValue,nValue + dEPS_Double));
    assert(Unequal(nValue + dEPS_Double,nValue));
    assert(!Unequal(nValue + dEPS_Double,nValue,dEPS_Third));
    assert(!Unequal(nValue,nValue + dEPS_Double,dEPS_Third));
    assert(Unequal(nValue + dEPS_Double * 2,nValue,dEPS_Third));
    assert(Unequal(nValue,nValue + dEPS_Double * 2,dEPS_Third));

    //测试用例3: 小于测试
    assert(Less(nValue,nValue2));
    assert(!Less(nValue,nValue + dEPS_Half));
    assert(!Less(nValue + dEPS_Half , nValue));
    assert(!Less(nValue + dEPS_Half,nValue + dEPS_Half));
    assert(Less(nValue,nValue + dEPS_Double));
    assert(!Less(nValue + dEPS_Double,nValue));
    assert(!Less(nValue + dEPS_Double,nValue,dEPS_Third));
    assert(!Less(nValue,nValue + dEPS_Double,dEPS_Third));
    assert(!Less(nValue + dEPS_Double * 2,nValue,dEPS_Third));
    assert(Less(nValue,nValue + dEPS_Double * 2,dEPS_Third));

    //测试用例4: 大于测试
    assert(!Great(nValue,nValue2));
    assert(!Great(nValue,nValue + dEPS_Half));
    assert(!Great(nValue + dEPS_Half , nValue));
    assert(!Great(nValue + dEPS_Half,nValue + dEPS_Half));
    assert(!Great(nValue,nValue + dEPS_Double));
    assert(Great(nValue + dEPS_Double,nValue));
    assert(!Great(nValue + dEPS_Double,nValue,dEPS_Third));
    assert(!Great(nValue,nValue + dEPS_Double,dEPS_Third));
    assert(Great(nValue + dEPS_Double * 2,nValue,dEPS_Third));
    assert(!Great(nValue,nValue + dEPS_Double * 2,dEPS_Third));

    //测试用例5: 小于等于测试
    assert(LessEqual(nValue,nValue2));
    assert(LessEqual(nValue,nValue));
    assert(LessEqual(nValue,nValue + dEPS_Half));
    assert(LessEqual(nValue + dEPS_Half , nValue));
    assert(LessEqual(nValue + dEPS_Half,nValue + dEPS_Half));
    assert(LessEqual(nValue,nValue + dEPS_Double));
    assert(!LessEqual(nValue + dEPS_Double,nValue));
    assert(LessEqual(nValue + dEPS_Double,nValue,dEPS_Third));
    assert(LessEqual(nValue,nValue + dEPS_Double,dEPS_Third));
    assert(!LessEqual(nValue + dEPS_Double * 2,nValue,dEPS_Third));
    assert(LessEqual(nValue,nValue + dEPS_Double * 2,dEPS_Third));

    //测试用例6: 大于等于测试
    assert(!GreatEqual(nValue,nValue2));
    assert(GreatEqual(nValue,nValue));
    assert(GreatEqual(nValue,nValue + dEPS_Half));
    assert(GreatEqual(nValue + dEPS_Half , nValue));
    assert(GreatEqual(nValue + dEPS_Half,nValue + dEPS_Half));
    assert(!GreatEqual(nValue,nValue + dEPS_Double));
    assert(GreatEqual(nValue + dEPS_Double,nValue));
    assert(GreatEqual(nValue + dEPS_Double,nValue,dEPS_Third));
    assert(GreatEqual(nValue,nValue + dEPS_Double,dEPS_Third));
    assert(GreatEqual(nValue + dEPS_Double * 2,nValue,dEPS_Third));
    assert(!GreatEqual(nValue,nValue + dEPS_Double * 2,dEPS_Third));
}

#endif //假如未定义_FLOATCOMPARE_HPP宏

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值