用于股票交易的大数四则运算

本人算是一枚小小的韭菜,并且会根据个人的兴趣爱好,编写一些关于炒股的程序,从去年末开始,我就一直在完善从新浪获取当前成交记录,并进行相应的计算的程序。在处理交易数据时,发现成交数据用浮点数运算难以避免固有的误差.因此实现一个精确的数据运算法则是必须的.


#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 tList = Tokenize(num, ".");
    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;
}
 

你可能感兴趣的:(用于股票交易的大数四则运算)