I need to build a high precision calculator that will operate with very large numbers. The whole point is that storing the values in arrays as one digit goes to separate array cell is now allowed.
That is memory representation of number 335897294593872
like so:
int number[] = {3, 3, 5, 8, 9, 7, 2, 9, 4, 5, 9, 3, 8, 7, 2};
is not legit, nor:
char number[] = {3, 3, 5, 8, 9, 7, 2, 9, 4, 5, 9, 3, 8, 7, 2};
nor:
std::string number("335897294593872");
What I want to do is to split up the whole number into 32bit chunks and store each individual chunk in separate array cell data type of which is u32int_t
.
Since I get the input from keyboard I store all values in std::string
initially and later put them in integer arrays to perform operations.
How do I put binary representation of a large number into an integer array filling in all bits properly?
I'm using standard C++ libraries only
I want to be able to add, subtract, multiply, divide those arrays with large numbers so I mean not to merely cut the string up and store decimal representation in integer array, but rather preserve bits order of the number itself to be able to calculate carry.
This is a rather naïve solution:
Source Code:
#include <iomanip>
#include <iostream>
#include <string>
#include <vector>
#include <algorithm>
std::vector<uint32_t> toBigInt(std::string text)
{
// convert string to BCD-like
for (char &c : text) c -= '0';
// build result vector
std::vector<uint32_t> value(1, 0);
uint32_t bit = 1;
for (;;) {
// set next bit if last digit is odd
if (text.back() & 1) value.back() |= bit;
// divide BCD-like by 2
bool notNull = false; int carry = 0;
for (char &c : text) {
const int carryNew = c & 1;
c /= 2; c += carry * 5;
carry = carryNew;
notNull |= c;
}
if (!notNull) break;
// shift bit
bit <<= 1;
if (!bit) {
value.push_back(0); bit = 1;
}
}
// done
return value;
}
std::ostream& operator<<(std::ostream &out, const std::vector<uint32_t> &value)
{
std::ios fmtOld(0); fmtOld.copyfmt(out);
for (size_t i = value.size(); i--;) {
out << std::hex << value[i] << std::setfill('0') << std::setw(sizeof (uint32_t) * 2);
}
out.copyfmt(fmtOld);
return out;
}
int main()
{
std::string tests[] = {
"0", "1",
"4294967295", // 0xffffffff
"4294967296", // 0x100000000
"18446744073709551615", // 0xffffffffffffff
"18446744073709551616", // 0x100000000000000
};
for (const std::string &test : tests) {
std::cout << test << ": " << toBigInt(test) << '\n';
}
return 0;
}
Output:
0: 0
1: 1
4294967295: ffffffff
4294967296: 100000000
18446744073709551615: ffffffffffffffff
18446744073709551616: 10000000000000000
Notes:
tests
, I used numbers where hex-code is simple to check by eyes.