Ok. Originally I was trying to write a program that would calculate pi to infinite decimal places. The calculus baesd algorithm I made for this is flawless, except that C++ can only handle 16 digits! So I did some looking around, for libraries and what not, to find something that supports a datatype of many more digits. Apperantly they don't exist (or they're not free anyway). So I've started writing my own program for handling numbers more precise than 16 digits.
It uses binary based logic to create files containing numbers, and a custom datatype that can contain a variable number of digits. So far I've completed the logic for addition and multiplication of these numbers. The problem is, it's way less efficient and much slower than using regular operations. I benchmarked it at 2.134 seconds to calculate 440000 * 3500. This calculation is instantaneos when c++ does all the math. I know there's probably some holes in the logic, since I'm a bit of a pothead, but here's the code:
#include<iostream>
#include<iomanip>
#include<fstream>
#include<cmath>
#include<ctime>
using namespace std;
const int MAX = 2056;
struct Num
{
int _MSBIndex;
bool _Sign;
bool _bd[MAX];
};
Num AddNum(Num&, Num&);
Num MultNum(Num&, Num&);
void Neg(Num&);
bool Equal(Num&, Num&);
void ShowNum(Num&);
void SaveNum(Num&, char[]);
void LoadNum(Num&, char[]);
void MakeNum(Num&, double);
void SolveMSB(Num&, int);
//Debug Funcs
void DoEfficiencyDebug();
int main()
{
Num nNumber;
Num nNumber2;
//MakeNum(nNumber, 1);
//SaveNum(nNumber, "One.bin");
MakeNum(nNumber2, 440000); //303milli--|
MakeNum(nNumber, 3500); //303milli--|
ShowNum (nNumber);
ShowNum (nNumber2);
ShowNum(MultNum(nNumber, nNumber2));
DoEfficiencyDebug();
cin.get();
return 0;
}
void DoEfficiencyDebug()
{
cout << "\n\nClock ticks for calculation: " << clock();
cout << "\n@ " << CLOCKS_PER_SEC << " For Duration: " << clock() / (CLOCKS_PER_SEC / 1000) << " milliseconds";
return;
}
bool Equal(Num &nNumber, Num &nNumber2)
{
bool bEqual = true;
if (nNumber._MSBIndex != nNumber2._MSBIndex)
bEqual = false;
else
{
for (int i = 0; i < nNumber._MSBIndex; i++)
{
if (nNumber._bd[i] != nNumber2._bd[i])
{
bEqual = false;
break;
}
}
}
return bEqual;
}
void SolveMSB(Num &nNumber, int iStartApprox)
{
for (int i = iStartApprox; i >= 0; i--)
if (nNumber._bd[i] == true)
{
nNumber._MSBIndex = i;
break;
}
return;
}
void Neg(Num &nNumber)
{
nNumber._Sign = (nNumber._Sign == true) ? false : true;
return;
}
Num MultNum(Num &nNumber, Num &nNumber2)
{
Num nReturn = {0};
Num nCount = {0};
Num nOne = {0};
LoadNum(nOne, "One.bin");
while (!Equal(nCount, nNumber2))
{
nCount = AddNum(nCount, nOne);
nReturn = AddNum(nReturn, nNumber);
}
SolveMSB(nReturn, (nNumber._MSBIndex + nNumber2._MSBIndex));
//SolveMSB(nReturn, MAX); //DEBUG ONLY
return nReturn;
}
Num AddNum(Num &nNumber, Num &nNumber2)
{
Num nReturn = {0};
int iMSB = 0;
bool bCarry = false;
if (nNumber._MSBIndex >= nNumber2._MSBIndex)
iMSB = nNumber._MSBIndex;
else
iMSB = nNumber2._MSBIndex;
//the actual addition logic
for (int i = 0; i <= iMSB + 1; i++)
{
if (nNumber._bd[i] == true && nNumber2._bd[i] == true && bCarry == false)
{
nReturn._bd[i] = false;
bCarry = true;
}
else if (nNumber._bd[i] == true && nNumber2._bd[i] == true && bCarry == true)
{
nReturn._bd[i] = true;
bCarry = true;
}
else if ((nNumber._bd[i] != nNumber2._bd[i]) && bCarry == true)
{
nReturn._bd[i] = false;
bCarry = true;
}
else if ((nNumber._bd[i] != nNumber2._bd[i]) && bCarry == false)
{
nReturn._bd[i] = true;
bCarry = false;
}
if (nNumber._bd[i] == false && nNumber2._bd[i] == false && bCarry == true)
{
nReturn._bd[i] = true;
bCarry = false;
}
}
SolveMSB(nReturn, iMSB + 1);
//SolveMSB(nReturn, MAX); //DEBUG ONLY
return nReturn;
}
void SaveNum(Num &nNumber, char szFilename[])
{
ofstream outFile;
outFile.open(szFilename, ios::out | ios::binary);
outFile.write(reinterpret_cast<char*>(&nNumber), sizeof(Num));
outFile.close();
return;
}
void LoadNum(Num &nNumber, char szFilename[])
{
ifstream outFile;
outFile.open(szFilename, ios::in | ios::binary);
outFile.read(reinterpret_cast<char*>(&nNumber), sizeof(Num));
outFile.close();
return;
}
void MakeNum(Num &nNumber, double dEntry)
{
bool bMSB = false;
bool bMSBset = false;
dEntry+= 1;
for (int i = MAX; i >= 0; i--)
{
if ((dEntry - (pow(2, i))) > 0)
{
bMSB = true;
dEntry -= (pow(2, i));
nNumber._bd[i] = true;
}
else
nNumber._bd[i] =false;
if (bMSB == true && bMSBset == false)
{
nNumber._MSBIndex = i;
bMSBset = true;
}
if (dEntry == 0)
break;
}
return;
}
void ShowNum(Num &nNumber)
{
double dAdder = 0;
bool bShowFlag = false;
int iFour = 0;
int iZeros = 0;
cout << "Most Significant Bit Index: " << nNumber._MSBIndex << endl;
cout << "Binary Form: ";
//Binary display algorithm, displays in 4's
iZeros = nNumber._MSBIndex + 1;
for (int ii = 0; ii <= nNumber._MSBIndex; ii++)
{
if ((iZeros - 4) >= 0)
iZeros -= 4;
else
break;
}
iZeros = 4 - iZeros;
if (iZeros >= 4)
iZeros -= 4;
for (int i = nNumber._MSBIndex + iZeros; i >= 0; i--)
{
if (iFour >= 4)
{
cout << " ";
iFour = 0;
}
iFour++;
cout << nNumber._bd[i];
if (nNumber._bd[i] == true)
{
dAdder += pow(2, i) ;
}
}
cout << "\nDecimal Form: ";
cout << setprecision(15) << dAdder << endl;
cout << endl;
return;
}
wow...it's longer than i remembered. sorry. any help increasing the efficiency of this code would be immensly appreciated!