本人算是一枚小小的韭菜,并且会根据个人的兴趣爱好,编写一些关于炒股的程序,从去年末开始,我就一直在完善从新浪获取当前成交记录,并进行相应的计算的程序。在处理交易数据时,发现成交数据用浮点数运算难以避免固有的误差.因此实现一个精确的数据运算法则是必须的.
#define DEC_BIT 5
#define INT1_DEC_VAL 100000
class Number
{
public:
Number(const std::string& str);
Number( const Number& num);
Number();
Number( INT64 val);
Number(int val);
Number(float val); //浮点输入会有误差的,只定义不实现
Number(double val); //只定义不实现
virtual ~Number();
void SetNumber(const Number& num);
void SetNumber(const std::string& num);
void SetNumber(INT64 val);
const Number operator -() const;
Number operator +(const Number& num);
Number operator -(const Number& num);
Number operator *(const Number& num);
Number operator /(const Number& num);
const Number Add(const Number& num)const;
const Number Sub(const Number& num)const;
const Number Mul(const Number& num)const;
const Number Dev(const Number& num)const;
void operator +=(const Number& num);
void operator -=(const Number& num);
void operator *=(const Number& num);
void operator /=(const Number& num);
bool operator ==(const Number& num);
bool operator !=(const Number& num);
bool operator >(const Number& num);
bool operator <(const Number& num);
bool operator >=(const Number& num);
bool operator <=(const Number& num);
const bool equal(const Number& num)const;
const bool notEqual(const Number& num)const;
const bool larger(const Number& num)const;
const bool less(const Number& num)const;
const bool largEqual(const Number& num)const;
const bool lessEqual(const Number& num)const;
const std::string toString() const;
const std::string toIntString() const;
const std::string toD1String() const;
const std::string toD2String() const;
const std::string toD3String() const;
#if !QT_NONE
const QString toQString()const;
const QString toIntQString()const;
const QString toD1QString() const;
const QString toD2QString() const;
const QString toD3QString() const;
#endif
const double toDouble()const;
const bool IsZero() const;
const bool IsInt() const
{
return (mValue%INT1_DEC_VAL) == 0;
}
const int toInt32() const
{
return (mValue / INT1_DEC_VAL);
}
const INT64 toInt64() const
{
return (mValue / INT1_DEC_VAL);
}
private:
void SetNumber(INT64 iVal, INT64 iDec);
void GenerateText();
INT64 ParseDecVal(const std::string& str);
void IntToDec(unsigned long iDec, unsigned int* dec);
private:
std::string mText;
INT64 mValue; //扩大了DEC_BIT(5)位的小数
};
Number operator +(const Number& num0, const Number& num);
Number operator -(const Number& num0, const Number& num);
Number operator *(const Number& num0, const Number& num);
Number operator /(const Number& num0, const Number& num);
bool operator ==(const Number& num0, const Number& num);
bool operator !=(const Number& num0, const Number& num);
bool operator >(const Number& num0, const Number& num);
bool operator <(const Number& num0, const Number& num);
bool operator >=(const Number& num0, const Number& num);
bool operator <=(const Number& num0, const Number& num);
int I64ToBytes(INT64 val, U8* buff, int maxLen);
int BytesToI64(INT64& val, const U8* buff, int len);
//注只有2位小数,储存时会转为整数,buff中的第1个数组中的前3bit代表数组的长度,并且最大数据不能大于
//1F FFFF FFFF FFFF
int NumberToBytes(const Number& num, U8* buff, int maxLen);
int BytesToNumber(Number& number, const U8* buff, int len);
Number::Number(const std::string& str)
{
SetNumber(str);
}
Number::Number(const Number& num)
{
SetNumber(num);
}
Number::Number() :mValue(0), mText("0")
{
SetNumber(0);
}
Number::Number(INT64 val)
{
SetNumber(val);
}
Number::Number(int val)
{
SetNumber(val);
}
Number::~Number()
{
}
void Number::SetNumber(const Number& num)
{
mText = num.mText;
mValue = num.mValue;
return;
}
void Number::SetNumber(const std::string& num)
{
if (num.empty())
{
SetNumber(0);
return;
}
INT64 lVal = 0;
INT64 iDec = 0;
std::vector
lVal = Atol(tList[0].c_str());
unsigned long size = tList.size();
if (size == 2)
{
int dec[5] = { 0 };
iDec = ParseDecVal(tList[1]);
if (lVal < 0)
{
iDec = -iDec;
}
else if (lVal == 0 && tList[0].size() >= 1 && tList[0][0] == '-')
{
iDec = -iDec;
}
}
SetNumber(lVal, iDec);
return;
}
void Number::SetNumber(INT64 val)
{
SetNumber(val, 0);
return ;
}
void Number::SetNumber(INT64 iVal, INT64 iDec)
{
mValue = iVal*INT1_DEC_VAL + iDec;
GenerateText();
}
const Number Number::operator -() const
{
Number t = *this;
t.mValue = -t.mValue;
t.GenerateText();
return t;
}
Number Number::operator +(const Number& num)
{
return Add(num);
}
Number Number::operator -(const Number& num)
{
return Sub(num);
}
Number Number::operator *(const Number& num)
{
return Mul(num);
}
Number Number::operator /(const Number& num)
{
return Dev(num);
}
const Number Number::Add(const Number& num)const
{
Number ret;
ret.mValue = mValue + num.mValue;
ret.GenerateText();
return ret;
}
const Number Number::Sub(const Number& num)const
{
Number ret = -num;
ret = *this + ret;
return ret;
}
const Number Number::Mul(const Number& num)const
{
Number ret;
INT64 a1 = mValue / INT1_DEC_VAL;
INT64 b1 = mValue % INT1_DEC_VAL;
INT64 a2 = num.mValue / INT1_DEC_VAL;
INT64 b2 = num.mValue % INT1_DEC_VAL;
//ret.mValue = mValue*num.mValue; //这个有问题
//ret.mValue /= INT1_DEC_VAL;
ret.mValue = a1*a2*INT1_DEC_VAL + (a1*b2 + a2*b1) + (b1*b2) / INT1_DEC_VAL;
ret.GenerateText();
return ret;
}
const Number Number::Dev(const Number& num)const
{
Number ret;
if (num.mValue == 0)
{
return ret;
}
double val = (double)mValue / num.mValue;
val *= INT1_DEC_VAL;
val = val > 0 ? val + 0.5 : val - 0.5;
ret.mValue = val;
ret.GenerateText();
return ret;
}
void Number::operator +=(const Number& num)
{
Number retNum = *this + num;
SetNumber(retNum);
}
void Number::operator -=(const Number& num)
{
Number retNum = *this - num;
SetNumber(retNum);
}
void Number::operator *=(const Number& num)
{
Number retNum = (*this)*(num);
SetNumber(retNum);
}
void Number::operator /=(const Number& num)
{
Number retNum = (*this) / (num);
SetNumber(retNum);
}
bool Number::operator ==(const Number& num)
{
return equal(num);
}
bool Number::operator !=(const Number& num)
{
return !(equal(num));
}
bool Number::operator >(const Number& num)
{
return larger(num);
}
bool Number::operator <(const Number& num)
{
return less(num);
}
bool Number::operator >=(const Number& num)
{
return largEqual(num);
}
bool Number::operator <=(const Number& num)
{
return lessEqual(num);
}
const bool Number::equal(const Number& num)const
{
return mValue == num.mValue;
}
const bool Number::notEqual(const Number& num)const
{
return mValue != num.mValue;
}
const bool Number::larger(const Number& num)const
{
return mValue > num.mValue;
}
const bool Number::less(const Number& num)const
{
return mValue < num.mValue;
}
const bool Number::largEqual(const Number& num)const
{
return mValue >= num.mValue;
}
const bool Number::lessEqual(const Number& num)const
{
return mValue <= num.mValue;
}
const std::string Number::toString() const
{
return mText;
}
const std::string Number::toIntString() const
{
INT64 iVal = mValue / INT1_DEC_VAL;
char buff[256] = { 0 };
sprintf_s(buff, "%I64d", iVal);
return buff;
}
const std::string Number::toD1String() const
{
Number temp = *this + Number("0.05");
if (mValue < 0)
{
temp = *this + Number("-0.05");
}
INT64 tVal = temp.mValue;
int iSig = tVal < 0 ? -1 : 1;
INT64 iVal = tVal < 0 ? -tVal : tVal;
int c = DEC_BIT - 1;
int t = 0;
int intDec = INT1_DEC_VAL;
while (t < c)
{
iVal /= 10;
intDec /= 10;
t++;
}
INT64 iDec = iVal%intDec;
iVal /= intDec;
char tBuff[128] = { 0 };
if (iSig < 0)
{
sprintf_s(tBuff, "-%I64d.%01I64d", iVal, iDec);
}
else
{
sprintf_s(tBuff, "%I64d.%01I64d", iVal, iDec);
}
return tBuff;
}
const std::string Number::toD2String() const
{
Number temp = *this + Number("0.005");
if (mValue < 0)
{
temp = *this + Number("-0.005");
}
INT64 tVal = temp.mValue;
int iSig = tVal < 0 ? -1 : 1;
INT64 iVal = tVal < 0 ? -tVal : tVal;
int c = DEC_BIT - 2;
int t = 0;
int intDec = INT1_DEC_VAL;
while (t < c)
{
iVal /= 10;
intDec /= 10;
t++;
}
INT64 iDec = iVal%intDec;
iVal /= intDec;
char tBuff[128] = { 0 };
if (iSig < 0)
{
sprintf_s(tBuff, "-%I64d.%02I64d", iVal, iDec);
}
else
{
sprintf_s(tBuff, "%I64d.%02I64d", iVal, iDec);
}
return tBuff;
}
const std::string Number::toD3String() const
{
Number temp = *this + Number("0.0005");
if (mValue < 0)
{
temp = *this + Number("-0.0005");
}
INT64 tVal = temp.mValue;
int iSig = tVal < 0 ? -1 : 1;
INT64 iVal = tVal < 0 ? -tVal : tVal;
int c = DEC_BIT - 3;
int t = 0;
int intDec = INT1_DEC_VAL;
while (t < c)
{
iVal /= 10;
intDec /= 10;
t++;
}
INT64 iDec = iVal%intDec;
iVal /= intDec;
char tBuff[128] = { 0 };
if (iSig < 0)
{
sprintf_s(tBuff, "-%I64d.%03I64d", iVal, iDec);
}
else
{
sprintf_s(tBuff, "%I64d.%03I64d", iVal, iDec);
}
return tBuff;
}
#if !QT_NONE
const QString Number::toQString()const
{
return mText.c_str();
}
const QString Number::toIntQString()const
{
return toIntString().c_str();
}
const QString Number::toD1QString() const
{
return toD1String().c_str();
}
const QString Number::toD2QString() const
{
return toD2String().c_str();
}
const QString Number::toD3QString() const
{
return toD3String().c_str();
}
#endif
const bool Number::IsZero() const
{
return mValue == 0;
}
void Number::GenerateText()
{
int iSig = mValue >= 0 ? 1 : -1;
INT64 val = mValue >= 0 ? mValue : -mValue;
INT64 iVal = val / INT1_DEC_VAL;
INT64 remd = val % INT1_DEC_VAL;
char buff[256] = { 0 };
if (iSig < 0 && remd > 0)
{
sprintf_s(buff, "-%I64d.%05I64d", iVal, remd);
}
else if (iSig < 0 && remd == 0)
{
sprintf_s(buff, "-%I64d", iVal);
}
else if (remd > 0)
{
sprintf_s(buff, "%I64d.%05I64d", iVal, remd);
}
else
{
sprintf_s(buff, "%I64d", iVal);
}
mText = buff;
}
INT64 Number::ParseDecVal(const std::string& str)
{
int dec[DEC_BIT] = { 0 };
unsigned int size = DEC_BIT;
if (str.size() < DEC_BIT)
{
size = str.size();
}
for (unsigned int i = 0; i < size; i++)
{
dec[i] = str[i] - '0';
}
INT64 val = dec[0];
for (int i = 1; i < DEC_BIT; i++)
{
val *= 10;
val += dec[i];
}
return val;
}
const double Number::toDouble()const
{
double ret = (double)mValue/INT1_DEC_VAL;
return ret;
}
/
Number operator +(const Number& num0, const Number& num)
{
Number retNum = num0.Add(num);
return retNum;
}
Number operator -(const Number& num0, const Number& num)
{
Number retNum = num0.Sub(num);
return retNum;
}
Number operator *(const Number& num0, const Number& num)
{
Number retNum = num0.Mul(num);
return retNum;
}
Number operator /(const Number& num0, const Number& num)
{
Number retNum = num0.Dev(num);
return retNum;
}
bool operator ==(const Number& num0, const Number& num)
{
return num0.equal(num);
}
bool operator !=(const Number& num0, const Number& num)
{
return !(num.equal(num0));
}
bool operator >(const Number& num0, const Number& num)
{
return num0.larger(num);
}
bool operator <(const Number& num0, const Number& num)
{
return num0.less(num);
}
bool operator >=(const Number& num0, const Number& num)
{
return num0.largEqual(num);
}
bool operator <=(const Number& num0, const Number& num)
{
return num0.lessEqual(num);
}
///
INT64 Square(int bVal, int count)
{
INT64 ret = bVal;
int i = 1;
while (i < count)
{
ret *= bVal;
i++;
}
return ret;
}
int I64ToBytes(INT64 val, U8* buff, int maxLen)
{
INT64 iVal = val;
if (iVal < 0)
{
iVal = 0;
}
else if (iVal > 0x1FFFFFFFFFFFFF)
{
iVal = 0x1FFFFFFFFFFFFF;
}
int count = 0;
for (int i = 5; i <= 64; i += 8)
{
count++;
INT64 ck = Square(2, i);
if (iVal <= ck)
{
break;
}
}
if (count == 1)
{
buff[0] = iVal & 0x1F;
buff[0] += (U8)(count << 5);
}
else if (count == 2)
{
buff[0] = (U8)((iVal & 0x1F00) >> 8);
buff[1] = (U8)((iVal & 0xFF));
buff[0] += (U8)(count << 5);
}
else if (count == 3)
{
buff[0] = (U8)((iVal & 0x1F0000) >> 16);
buff[1] = (U8)((iVal & 0xFF00) >> 8);
buff[2] = (U8)((iVal & 0xFF));
buff[0] += (U8)(count << 5);
}
else if (count == 4)
{
buff[0] = (U8)((iVal & 0x1F000000) >> 24);
buff[1] = (U8)((iVal & 0xFF0000) >> 16);
buff[2] = (U8)((iVal & 0xFF00) >> 8);
buff[3] = (U8)((iVal & 0xFF));
buff[0] += (U8)(count << 5);
}
else if (count == 5)
{
buff[0] = (U8)((iVal & 0x1F00000000) >> 32);
buff[1] = (U8)((iVal & 0xFF000000) >> 24);
buff[2] = (U8)((iVal & 0xFF0000) >> 16);
buff[3] = (U8)((iVal & 0xFF00) >> 8);
buff[4] = (U8)((iVal & 0xFF));
buff[0] += (U8)(count << 5);
}
else if (count == 6)
{
buff[0] = (U8)((iVal & 0x1F0000000000) >> 40);
buff[1] = (U8)((iVal & 0xFF00000000) >> 32);
buff[2] = (U8)((iVal & 0xFF000000) >> 24);
buff[3] = (U8)((iVal & 0xFF0000) >> 16);
buff[4] = (U8)((iVal & 0xFF00) >> 8);
buff[5] = (U8)((iVal & 0xFF));
buff[0] += (U8)(count << 5);
}
else if (count == 7)
{
buff[0] = (U8)((iVal & 0x1F000000000000) >> 48);
buff[1] = (U8)((iVal & 0xFF0000000000) >> 40);
buff[2] = (U8)((iVal & 0xFF00000000) >> 32);
buff[3] = (U8)((iVal & 0xFF000000) >> 24);
buff[4] = (U8)((iVal & 0xFF0000) >> 16);
buff[5] = (U8)((iVal & 0xFF00) >> 8);
buff[6] = (U8)((iVal & 0xFF));
buff[0] += (U8)(count << 5);
}
return count;
}
int BytesToI64(INT64& val, const U8* buff, int len)
{
INT64 num = 0;
Number ret;
int count = (buff[0] >> 5);
if (count > len || count > 7)
{
return 0;
}
if (count == 7)
{
num = ((INT64)(buff[0] & 0x1F) << 48);
num += ((INT64)buff[1] << 40);
num += ((INT64)buff[2] << 32);
num += ((INT64)buff[3] << 24);
num += ((INT64)buff[4] << 16);
num += ((INT64)buff[5] << 8);
num += ((INT64)buff[6]);
}
else if (count == 6)
{
num += ((INT64(buff[0] & 0x1F)) << 40);
num += ((INT64)buff[1] << 32);
num += ((INT64)buff[2] << 24);
num += ((INT64)buff[3] << 16);
num += ((INT64)buff[4] << 8);
num += ((INT64)buff[5]);
}
else if (count == 5)
{
num += ((INT64)(buff[0] & 0x1F) << 32);
num += ((INT64)buff[1] << 24);
num += ((INT64)buff[2] << 16);
num += ((INT64)buff[3] << 8);
num += ((INT64)buff[4]);
}
else if (count == 4)
{
num += ((INT64)(buff[0] & 0x1F) << 24);
num += ((INT64)buff[1] << 16);
num += ((INT64)buff[2] << 8);
num += ((INT64)buff[3]);
}
else if (count == 3)
{
num += ((INT64)(buff[0] & 0x1F) << 16);
num += ((INT64)buff[1] << 8);
num += ((INT64)buff[2]);
}
else if (count == 2)
{
num += ((INT64)(buff[0] & 0x1F) << 8);
num += ((INT64)buff[1]);
}
else if (count == 1)
{
num += (INT64)(buff[0] & 0x1F);
}
return count;
}
int NumberToBytes(const Number& num, U8* buff, int maxLen)
{
int count = 0;
INT64 iVal = (num * 100).toInt64();
return I64ToBytes(iVal, buff, maxLen);
}
int BytesToNumber(Number& number, const U8* buff, int len)
{
INT64 iVal = 0;
int count = BytesToI64(iVal, buff, len);
INT64 v0 = iVal / 100;
INT64 v1 = iVal % 100;
char strBuff[64] = { 0 };
sprintf_s(strBuff, "%I64d.%02I64d", v0, v1);
number = Number(strBuff);
return count;
}