In honor to
Emilio Garavaglia ive replaced the original code by a more c++ like solution. But im afraid there is no perfect solution.
content of CNumber.h:
#ifndef __CNUMBER_H
#define __CNUMBER_H
#include <tchar.h>
template <class TI> const TI& myminimum(const TI& a,const TI& b){ return a<b?a:b; }
template <class TI> const TI& mymaximum(const TI& a,const TI& b){ return a<b?b:a; }
class bNumber
{
public:
bNumber();
~bNumber();
protected:
void d(const unsigned int n);
void t(const unsigned int n);
protected:
unsigned int _ndigits;
unsigned char* _adigits;
TCHAR* _tmpout;
};
class CNumber : bNumber
{
public:
CNumber();
CNumber(CNumber& n);
CNumber(const unsigned int z);
CNumber(const TCHAR* s);
~CNumber();
operator const TCHAR* ();
CNumber& operator = (CNumber& n);
CNumber& operator = (const TCHAR* s);
CNumber& operator = (const unsigned int z);
CNumber operator *= (const unsigned char m);
CNumber& operator += (CNumber& add);
CNumber operator * (const unsigned char m);
CNumber operator * (CNumber& mul);
CNumber& exp(unsigned int e);
unsigned char operator [] (const unsigned int ix);
unsigned int length();
const TCHAR* pad(const unsigned int n,const TCHAR c);
private:
inline
unsigned int m10(unsigned int d,unsigned char& c){ c=d%10; return d/10; }
void trim();
};
#endif // __CNUMBER_H
content of CNumber.cpp:
#include "CNumber.h"
bNumber::bNumber()
{
_ndigits = 0;
_adigits = 0;
_tmpout = 0;
}
bNumber::~bNumber()
{
if(_adigits) delete [] _adigits;
if(_tmpout) delete [] _tmpout;
}
void bNumber::d(const unsigned int n)
{
unsigned char* p = new unsigned char[n];
unsigned int i,m;
if(_adigits)
{
for(i=0,m=myminimum(n,_ndigits);i<m;i++) p[i] = _adigits[i];
delete [] _adigits;
}
_adigits = p;
}
void bNumber::t(const unsigned int n)
{
TCHAR* p = new TCHAR[n];
if(_tmpout) delete [] _tmpout;
_tmpout = p;
}
CNumber::CNumber()
{
}
CNumber::CNumber(CNumber& n)
{
operator = (n);
}
CNumber::CNumber(const unsigned int z)
{
operator = (z);
}
CNumber::CNumber(const TCHAR* s)
{
operator = (s);
}
CNumber::~CNumber()
{
}
CNumber::operator const TCHAR* ()
{
return pad(0,' ');
}
CNumber& CNumber::operator = (CNumber& n)
{
unsigned int i;
d(_ndigits=n._ndigits);
for(i=0;i<_ndigits;i++) _adigits[i] = n._adigits[i];
return *this;
}
CNumber& CNumber::operator = (const TCHAR* s)
{
unsigned int i,n = _tcslen(s);
d(_ndigits=n);
for(i=0;i<n;i++) _adigits[i] = s[i]-'0';
return *this;
}
CNumber& CNumber::operator = (const unsigned int z)
{
unsigned int i,r = z;
d(_ndigits=10);
for(i=0;i<10;i++){ _adigits[9-i]=r%10; r/=10; }
return *this;
}
CNumber CNumber::operator * (const unsigned char m)
{
return CNumber(*this) *= m;
}
CNumber CNumber::operator *= (const unsigned char m)
{
unsigned int i,r=0;
d(++_ndigits);
for(i=_ndigits-1;i;i--)
{
r += (unsigned int)m * (unsigned int)_adigits[i-1];
r = m10(r,_adigits[i]);
}
_adigits[i] = (unsigned char)r;
trim();
return *this;
}
CNumber& CNumber::operator += (CNumber& add)
{
unsigned int i,n,r;
n = mymaximum(_ndigits,add._ndigits);
d(1+n);
for(r=i=0;i<n;i++)
{
r += operator[](i) + add[i];
r = m10(r,_adigits[n-i]);
}
for(;i<_ndigits;i++)
{
r += operator[](i);
r = m10(r,_adigits[n-i]);
}
for(;i<add._ndigits;i++)
{
r += add[i];
r = m10(r,_adigits[n-i]);
}
_adigits[0] = r;
_ndigits = 1 + n;
trim();
return *this;
}
CNumber CNumber::operator * (CNumber& mul)
{
CNumber n,m;
unsigned int i;
for(i=0;i<mul.length();i++)
{
m = (*this) * mul[i];
m.exp(i);
n += m;
}
return n;
}
unsigned char CNumber::operator [] (const unsigned int ix)
{
return ix<_ndigits?_adigits[_ndigits-ix-1]:0;
}
CNumber& CNumber::exp(unsigned int e)
{
if(_ndigits)
{
d(e+=_ndigits);
for(;_ndigits<e;_ndigits++) _adigits[_ndigits]=0;
}
return *this;
}
unsigned int CNumber::length()
{
return _ndigits;
}
const TCHAR* CNumber::pad(const unsigned int n,const TCHAR c)
{
unsigned int i,o,x;
for(i=0;(i<_ndigits)&&(0==_adigits[i]);i++);
x = mymaximum(n,_ndigits-i); t(1+x);
for(o=0;o<(x-(_ndigits-i));o++) _tmpout[o] = c;
for(;i<_ndigits;i++) _tmpout[o++] = '0' + _adigits[i];
_tmpout[o] = 0;
return _tmpout;
}
void CNumber::trim()
{
unsigned int i,o;
for(i=0;(i<_ndigits)&&(0==_adigits[i]);i++);
if(i)
{
for(o=0;i<_ndigits;i++) _adigits[o++]=_adigits[i];
_ndigits = o;
}
}
content of main.cpp:
#pragma once
#include <stdio.h>
#include "CNumber.h"
int _tmain(int argc, _TCHAR* argv[])
{
{
enum{ PAD = 40, };
CNumber a = _T("905427184367094827395");
CNumber b = _T("4838203673416526153");
CNumber c;
unsigned int i;
if(1<argc) a = argv[1];
if(2<argc) b = argv[2];
_tprintf(__T("%s x %s = \r\n"),(const TCHAR*)a,(const TCHAR*)b);
_tprintf(__T("-----------------------------\r\n"));
for(i=0;i<b.length();i++)
{
c = a * b[i];
c.exp(i);
if(c.length()) _tprintf(__T("%s\r\n"),c.pad(PAD,' '));
}
_tprintf(__T("-----------------------------\r\n"));
c = a * b;
_tprintf(__T("%s\r\n"),c.pad(PAD,' '));
_tprintf(__T("=============================\r\n"));
_gettch();
}
return 0;
}
Best regards to the useful hints of
Emilio Garavaglia.