全面解决浮点数比较大小,四舍五入等问题

周成风 2009-09-11 10:45:25
呵呵,题目有点大,只为了吸引目光,不要多想。平时常遇到浮点数比较大小、四舍五入等问题,故自己写了个简单的double封装类WDouble。

麻烦有时间的帮我看看有没有什么问题,包括代码风格、程序错误,补充等。我能继续完善!拜谢。

WDouble.h


/**
* @file WDouble.h
* @brief double型变量封装,可以设置精度
* @author 沙漠乌鸦
* @date 2009-09-07
* @warning WDouble类暂时需要实现的功能
* 1) 设置全局的默认精度和单独的精度
* 2) 返回原始double值或运用精度计算后的值
* 3) 同时支持正、负数的格式化
* 3) 大小比较符<、>、<=、>=
* 4) ==、!=操作符
* 5) +、-、*、/、+=、-=、*=、/=操作符
* 6) <<、>>操作符
*/

#pragma once
#include <iostream>
using std::ostream;
using std::istream;

namespace wuya
{

class WDouble
{
public:
WDouble(void);
WDouble(double dVal,size_t nPrecision = m_nPrecisionDef);
WDouble(const WDouble& dVal);
~WDouble(void) throw();

WDouble& operator = (const WDouble& dVal);
WDouble& operator = (double dVal);

// operator
friend inline bool operator == (const WDouble& dVal1,const WDouble& dVal2);
friend inline bool operator != (const WDouble& dVal1,const WDouble& dVal2);
friend inline bool operator < (const WDouble& dVal1,const WDouble& dVal2);
friend inline bool operator > (const WDouble& dVal1,const WDouble& dVal2);
friend inline bool operator <= (const WDouble& dVal1,const WDouble& dVal2);
friend inline bool operator >= (const WDouble& dVal1,const WDouble& dVal2);
friend inline void operator += (WDouble& dVal1,const WDouble& dVal2); ///< 精度以第一个操作数为准
friend inline void operator -= (WDouble& dVal1,const WDouble& dVal2);
friend inline void operator *= (WDouble& dVal1,const WDouble& dVal2);
friend inline void operator /= (WDouble& dVal1,const WDouble& dVal2);
friend inline WDouble operator + (const WDouble& dVal1,const WDouble& dVal2); ///< 精度以精度较大的为准
friend inline WDouble operator - (const WDouble& dVal1,const WDouble& dVal2);
friend inline WDouble operator * (const WDouble& dVal1,const WDouble& dVal2);
friend inline WDouble operator / (const WDouble& dVal1,const WDouble& dVal2);
friend inline ostream& operator << (ostream& os,const WDouble& object);
friend inline istream& operator >> (istream& os,WDouble& object);

/**
* @brief 设置WDouble精度
* @param [in]nPrecision 由于double型精度最大支持10位,该值范围为0-10,若非该范围值,则保留原精度
*/
void SetPrecision(size_t nPrecision);
/** @brief 返回WDoule精度 */
size_t GetPrecision() const;

/**
* @brief 返回double值,精度为WDouble保存精度
*/
double Get() const;
/**
* @brief 返回double值,精度为nPrecision
*/
double Get(size_t nPrecision) const;
/**
* @brief 返回输入的double值、未进行四舍五入
*/
double GetEnter() const;

static void SetPrecisionDef(size_t nPrecision);
static size_t GetPrecisionDef();

private:
/** @brief 对原始数据进行四舍五入计算 */
double Round(size_t nPrecision) const;

void Round();

private:
double m_dDbl; ///< 按照精度四舍五入后的double值
double m_dDblEnter; ///< 原始double值
size_t m_nPrecision; ///< double精度

static size_t m_nPrecisionDef; ///< 默认精度、值为1,即可以精确到0.1
};

inline bool operator == (const WDouble& dVal1,const WDouble& dVal2)
{
return dVal1.m_dDbl == dVal2.m_dDbl;
}
inline bool operator != (const WDouble& dVal1,const WDouble& dVal2)
{
return dVal1.m_dDbl != dVal2.m_dDbl;
}
inline bool operator < (const WDouble& dVal1,const WDouble& dVal2)
{
return dVal1.m_dDbl < dVal2.m_dDbl;
}
inline bool operator > (const WDouble& dVal1,const WDouble& dVal2)
{
return dVal1.m_dDbl > dVal2.m_dDbl;
}
inline bool operator <= (const WDouble& dVal1,const WDouble& dVal2)
{
return dVal1.m_dDbl <= dVal2.m_dDbl;
}
inline bool operator >= (const WDouble& dVal1,const WDouble& dVal2)
{
return dVal1.m_dDbl >= dVal2.m_dDbl;
}
inline void operator += (WDouble& dVal1,const WDouble& dVal2)
{
dVal1.m_dDblEnter += dVal2.m_dDblEnter;

// 以dVal1的精度为准
dVal1.Round();
}
inline void operator -= (WDouble& dVal1,const WDouble& dVal2)
{
dVal1.m_dDblEnter -= dVal2.m_dDblEnter;

// 以dVal1的精度为准
dVal1.Round();
}
inline void operator *= (WDouble& dVal1,const WDouble& dVal2)
{
dVal1.m_dDblEnter *= dVal2.m_dDblEnter;

// 以dVal1的精度为准
dVal1.Round();
}
inline void operator /= (WDouble& dVal1,const WDouble& dVal2)
{
dVal1.m_dDblEnter /= dVal2.m_dDblEnter;

// 以dVal1的精度为准
dVal1.Round();
dVal1.m_dDblEnter = dVal1.m_dDbl;
}
inline WDouble operator + (const WDouble& dVal1,const WDouble& dVal2)
{
size_t nPrecision;
if(dVal1.m_nPrecision > dVal2.m_nPrecision)
nPrecision = dVal1.m_nPrecision;
else
nPrecision = dVal2.m_nPrecision;

WDouble dVal(dVal1.m_dDbl + dVal2.m_dDbl,nPrecision);
return dVal;
}
inline WDouble operator - (const WDouble& dVal1,const WDouble& dVal2)
{
size_t nPrecision;
if(dVal1.m_nPrecision > dVal2.m_nPrecision)
nPrecision = dVal1.m_nPrecision;
else
nPrecision = dVal2.m_nPrecision;

WDouble dVal(dVal1.m_dDbl - dVal2.m_dDbl,nPrecision);
return dVal;
}
inline WDouble operator * (const WDouble& dVal1,const WDouble& dVal2)
{
size_t nPrecision;
if(dVal1.m_nPrecision > dVal2.m_nPrecision)
nPrecision = dVal1.m_nPrecision;
else
nPrecision = dVal2.m_nPrecision;

WDouble dVal(dVal1.m_dDbl * dVal2.m_dDbl,nPrecision);
return dVal;
}
inline WDouble operator / (const WDouble& dVal1,const WDouble& dVal2)
{
size_t nPrecision;
if(dVal1.m_nPrecision > dVal2.m_nPrecision)
nPrecision = dVal1.m_nPrecision;
else
nPrecision = dVal2.m_nPrecision;

WDouble dVal(dVal1.m_dDbl / dVal2.m_dDbl,nPrecision);
return dVal;
}
inline ostream& operator << (ostream& os,const WDouble& object)
{
os << object.m_dDbl;

return os;
}
inline istream& operator >> (istream& os,WDouble& object)
{
double dVal;
os >> dVal;

if(os)
{
object.m_dDblEnter = dVal;
object.Round();
}
else
object = WDouble();

return os;
}

};



WDouble.cpp

#include "StdAfx.h"
#include "WDouble.h"
#include <math.h>
#include <boost/cast.hpp>

namespace wuya
{

size_t WDouble::m_nPrecisionDef = 1;

WDouble::WDouble(void): m_dDbl(0.0),m_dDblEnter(0.0),m_nPrecision(m_nPrecisionDef)
{
}
WDouble::WDouble(double dVal,size_t nPrecision /* = m_nPrecisionDef */) : m_dDblEnter(dVal),m_nPrecision(nPrecision)
{
Round();
}
WDouble::WDouble(const WDouble& dVal)
:m_dDbl(dVal.m_dDbl)
,m_dDblEnter(dVal.m_dDblEnter)
,m_nPrecision(dVal.m_nPrecision)
{
}

WDouble::~WDouble(void) throw()
{
}

WDouble& WDouble::operator = (const WDouble& dVal)
{
if(&dVal == this)
return *this;

this->m_dDbl = dVal.m_dDbl;
this->m_dDblEnter = dVal.m_dDblEnter;
this->m_nPrecision = dVal.m_nPrecision;

return *this;
}
WDouble& WDouble::operator = (double dVal)
{
this->m_dDblEnter = dVal;
this->m_nPrecision = m_nPrecisionDef;

Round();

return *this;
}

void WDouble::SetPrecisionDef(size_t nPrecision)
{
m_nPrecisionDef = nPrecision;
}
size_t WDouble::GetPrecisionDef()
{
return m_nPrecisionDef;
}

void WDouble::SetPrecision(size_t nPrecision)
{
this->m_nPrecision = nPrecision;
}
size_t WDouble::GetPrecision() const
{
return m_nPrecision;
}
double WDouble::Get() const
{
return m_dDbl;
}
double WDouble::Get(size_t nPrecision) const
{
return Round(nPrecision);
}
double WDouble::GetEnter() const
{
return m_dDblEnter;
}

double WDouble::Round(size_t nPrecision) const
{
using namespace boost;

double dPow = pow(10.0,(int)nPrecision);
double dResult,dVal;
if(m_dDblEnter >= 0)
dVal = (m_dDblEnter * dPow + 0.5);
else
dVal = (m_dDblEnter * dPow - 0.5);

try
{
__int64 lVal = numeric_cast<__int64>(dVal);
dResult = lVal / dPow;
}
catch(bad_numeric_cast&)
{
dResult = 0.0;
}

return dResult;
}
void WDouble::Round()
{
m_dDbl = Round(m_nPrecision);
}

}



简单的测试代码:


#include "stdafx.h"
#include <iostream>
#include "WDouble.h"

using namespace wuya;
using namespace std;

int _tmain(int argc, _TCHAR* argv[])
{
double d1 = 0.5514;
double d2 = 0.5416;
WDouble dVal1 = d1;
WDouble dVal2 = d2;

cout << dVal1.Get() << endl;
cout << dVal2.Get() << endl;
cout << dVal1.Get(3) << endl;
cout << dVal2.Get(3) << endl;

cout << dVal1 << dVal2 << endl;

int iPrecision = 2;
WDouble::SetPrecisionDef(iPrecision);
cout << "Precision Changed is" << iPrecision << endl;

dVal1 = d1;
dVal2 = d2;

cout << dVal1.Get() << endl;
cout << dVal2.Get() << endl;

cout << WDouble(1.7808,3).Get() << endl;
cout << WDouble(-1.54,1).Get() << endl;
cout << WDouble(-1.535,2).Get() << endl;

dVal1 += dVal2;

cout << dVal1.Get() << endl;

WDouble dVal10;
cin >> dVal10;

cout << dVal10 << endl;

system("pause");

return 0;
}


代码中使用了boost库里面的numeric_cast,找出问题或提出意见的就给分!!
...全文
903 18 打赏 收藏 转发到动态 举报
写回复
用AI写文章
18 条回复
切换为时间正序
请发表友善的回复…
发表回复
非兔子_Logic0 2009-09-12
  • 打赏
  • 举报
回复
好帖留名
thy38 2009-09-12
  • 打赏
  • 举报
回复
最好不用Boost吧,毕竟那还是个试验性的库,我也在写个无限大数的库,也是忍痛去了Boost
beefliu 2009-09-12
  • 打赏
  • 举报
回复
帮顶
ppcfuns 2009-09-12
  • 打赏
  • 举报
回复
顶一下。。
井白人 2009-09-12
  • 打赏
  • 举报
回复
up
周成风 2009-09-12
  • 打赏
  • 举报
回复
[Quote=引用 13 楼 thy38 的回复:]
最好不用Boost吧,毕竟那还是个试验性的库,我也在写个无限大数的库,也是忍痛去了Boost
[/Quote]

其实我们公司鼓励使用boost,所以有些问题我也常用。比如智能指针。
麻烦大家提提这个WDouble的意见啊,就当没有使用boost.
周成风 2009-09-12
  • 打赏
  • 举报
回复
[Quote=引用 4 楼 healer_kx 的回复:]
code review~
[/Quote]

还没用用这个软件,不过谢谢了。

[Quote=引用 6 楼 fallening 的回复:]
cmath的一堆函数都不能用了?
把隐式转换操作符double重载一下吧

[/Quote]

恩,是该把这个加上。
pmerOFc 2009-09-11
  • 打赏
  • 举报
回复
[Quote=引用 7 楼 pmerofc 的回复:]
请教楼主一个问题
你的DBL_GIG是多少?
[/Quote]
抱歉,写错了
你的DBL_DIG是多少?
  • 打赏
  • 举报
回复
up
pmerOFc 2009-09-11
  • 打赏
  • 举报
回复
请教楼主一个问题
你的DBL_GIG是多少?
fallening 2009-09-11
  • 打赏
  • 举报
回复
cmath的一堆函数都不能用了?
把隐式转换操作符double重载一下吧
liuharris 2009-09-11
  • 打赏
  • 举报
回复
boost的库去掉吧,要不就更新最新的SDK
healer_kx 2009-09-11
  • 打赏
  • 举报
回复
code review~
drysea 2009-09-11
  • 打赏
  • 举报
回复
顶一个
周成风 2009-09-11
  • 打赏
  • 举报
回复
[Quote=引用 1 楼 wuyu637 的回复:]
最好把boost的库去掉吧。boost现在的支持性做的不好,很多环境下都没有安装。
[/Quote]

恩,等我找时间给去掉,就用了个转换。
wuyu637 2009-09-11
  • 打赏
  • 举报
回复
最好把boost的库去掉吧。boost现在的支持性做的不好,很多环境下都没有安装。
myhder 2009-09-11
  • 打赏
  • 举报
回复
up
不错
wangshiyang 2009-09-11
  • 打赏
  • 举报
回复
呵呵! 不错!
来这学习学习!

64,686

社区成员

发帖
与我相关
我的任务
社区描述
C++ 语言相关问题讨论,技术干货分享,前沿动态等
c++ 技术论坛(原bbs)
社区管理员
  • C++ 语言社区
  • encoderlee
  • paschen
加入社区
  • 近7日
  • 近30日
  • 至今
社区公告
  1. 请不要发布与C++技术无关的贴子
  2. 请不要发布与技术无关的招聘、广告的帖子
  3. 请尽可能的描述清楚你的问题,如果涉及到代码请尽可能的格式化一下

试试用AI创作助手写篇文章吧