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

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

 

//**********************************************************************
// 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宏

你可能感兴趣的:(C++源码分享(一):浮点数比较类)