I have a type BigInt which stores large numbers as an array of digits (0-9) in a char array called privately m_digitArray.
I am overloading arithmetic and relational operators to help in development. However, I could not get the multiplicative operator *= to work for me. The code I posted works for single digit operations in int * BigInt only while I'd prefer it work for any length number and for all int * BigInt, BigInt * int, and especially BigInt * BigInt operations. Like it works for 6 * bigInt (with a value of 6) = 36; but not 11 * bigInt (with a value of 10).
BigInt.cpp
Overloaded operator in question
BigInt BigInt::operator *= (const BigInt &rhs){
int size = m_digitArraySize + rhs.getSize();
int* C = new int[size];
int s = size-1;
for(int j= rhs.getSize() - 1; j >= 0; j--){
int carry = 0;
int shift = s;
for(int i = m_digitArraySize - 1; i >= 0; i--){
int m = getDigit(i) * rhs.getDigit(j);
int sum = m + C[shift] + carry;
int num = sum % 10;
int c = sum/10;
C[shift] = num;
carry = c;
shift--;
}
C[shift]= C[shift] + carry;
s--;
}
reallocateArray(size);
// for(int i = 0; i < size < ++i){
// m_digitArray[i] = '0' + C[i];
// }
// Nothing being returned, printing to debug
for (int i = 0; i < size; ++i)
{
cout << C[i];
}
return *this;
}
// Overload the * operator for BigInt * BigInt operations
BigInt operator * (const BigInt &lhs, const BigInt &rhs){
return BigInt(lhs) *= rhs;
}
// Overload the * operator for BigInt * int operations
BigInt operator * (const BigInt &lhs, int num){
return BigInt(lhs) *= num;
}
// Overload the * operator for int * BigInt operations
BigInt operator * (int num, const BigInt &rhs){
return BigInt(rhs) *= num;
}
You have an error in the logic in that you're coding operator * as something that implements operator *= to do it's work. Your problem is that calling:
x = y * z
shouldn't change the value of "y". That's an unwanted side-effect. But if you define operator* for your BigInt as using *= to get the result, that's exactly what it would do. Also if you do that, then calling
x = z * y
will cause different behaviour to "x = y * z", because now z is changed instead of y, which violates basic commutative laws of mathematics.
Start with operator* and operator=, then construct operator *= by chaining together calls to those.
operator* should create a new BigInt, then multiply the two input BigInts (passed as "const BigInt&"), then return the newly-created BigInt. To optimize this, you look into move constructors. but it's not necessary.
operator= is your copy assignment function, it should be later built to use move semantics, but that's also not critical
Then after that you can use *= to combine the two other functions, by merely writing something simple such as:
BigInt BigInt::operator*=(const BigInt &rhs)
{
(*this) = (*this) * rhs;
return (*this);
}
Well I was able to figure it out after some help. Here's the solution to the problem:
BigInt BigInt::operator *= (const BigInt &rhs){
// Create new BigInt to make changes non-destructively
BigInt numbers;
// A safe capacity size for the new BigInt
int size = m_digitArraySize + rhs.getSize();
// If either number is negative, set self to negative
if(!m_isPositive || !rhs.isPositive())
numbers.initializeArray(size, false);
else
numbers.initializeArray(size, true);
// Go through the multiplier
for(int i = 0; i < rhs.getSize(); ++i){
int carry = 0;
// Go through the multiplicand
for(int j = 0; j < m_digitArraySize; ++j){
// The product of multiplicand and multiplier plus the sum of the previous digits and the carry
int product = (getDigit(j) * rhs.getDigit(i)) + numbers.getDigit(i + j) + carry;
// Reset carry, necessary if the product is just a digit
carry = 0;
// Set carry to the tens digit
carry = product / 10;
// Set product to the units digit
product = product % 10;
// Save to the new BigInt
numbers.setDigit(i +j, product);
}
// Inner loop cuts off near the end, continue the loop if there is a carry
int nextDigit = i + m_digitArraySize;
while(carry!=0){
int new_value = numbers.getDigit(nextDigit) + carry;
carry = 0;
carry = new_value / 10;
new_value = new_value % 10;
numbers.setDigit(nextDigit, new_value);
++nextDigit;
}
}
// Remove excess zeros
numbers.normalizeArray();
*this = numbers;
return *this;
}
Related
I'm implementing a BigInt in c++ and am trying to overload the multiplication operator. I'm storing large integers in a char vector.
vector<char> storage;
Here is what I did to implement operator*(int)
BigInt BigInt::operator*(int x)
{
int extra = 0;
int dec_mod = pow(10, this->storage.size());
for (auto & g : storage) {
g = g * x + extra;
int mod_g = g % dec_mod;
extra = g / dec_mod;
g = mod_g;
}
while (extra > 0) {
storage.push_back(extra % dec_mod);
extra /= dec_mod;
}
return *this;
}
The operator*(bigInt) function returns wrong answers. For example, 33 * 4 returns 1212 and not 132.This was my attempt at writing the overloaded operator* which takes a bigint object:
BigInt BigInt::operator*(BigInt bigN) {
int carry = 0;
for (int i = bigN.storage.size()-1; i >= 0; i--) {
for (int j = this->storage.size()-1; j >= 0; j--) {
int val = (this->storage.at(i) * bigN.storage.at(j)) + carry;
this->storage.push_back(val % 10);
carry = val / 10;
}
}
return *this;
}
It looks like the logic in the carry is flawed, but i'm not sure how to fix it.
I'm not sure how you're trying to do this, but here is a walkthrough of why you're getting the result 1212 instead of 132:
BigInt operator*(int x)// x is 4
{
// Let's say storage holds 33, that's
// {3, 3} in your char vector;
int extra = 0;
int dec_mod = pow(10, this->storage.size()); // dec_mod may be 100
for (auto & g : storage)
{
g = g * x + extra; // same as g = 3 * 4 + 0, g = 12
int mod_g = g % dec_mod; // same as mod_g = 12 % 100 = 12
extra = g / dec_mod; // same as 12 / 100 = 0
g = mod_g; // g = 12
}
// Exact same thing happens on the second iteration, your storage vector
// ends up as {12, 12};
// That's why your result is 1212
while (extra > 0) {
storage.push_back(extra % dec_mod);
extra /= dec_mod;
}
return *this;
}
I'm not sure how you are trying to do it, but here's my attempt, it's just as one would do it on paper:
#include <iostream>
#include <string>
#include <vector>
using namespace std;
struct BigInt
{
BigInt(std::string num) { for (auto &i : num) storage.push_back(i - 48); }
BigInt(std::vector<char> numVect) : storage(numVect) {}
vector<char> storage;
string getAsString()
{ string str; for (auto& i : storage) str += i + 48; return str; }
// Add 48 to turn 0 - 9 to ascii string.
vector<char> add(vector<char>& lhs, vector<char>& rhs)
// Add function only needed if number is multiplied by more than one digit.
{
// Fill with zeros to make both vectors same length.
int sizeDiff = (int)lhs.size() - (int)rhs.size();
if (sizeDiff < 0)
lhs.insert(lhs.begin(), abs(sizeDiff), 0);
else if (sizeDiff > 0)
rhs.insert(rhs.begin(), abs(sizeDiff), 0);
vector<char> resultVect;
int carry = 0;
for (int i = lhs.size() - 1; i >= 0; --i)
{
int result = lhs[i] + rhs[i] + carry;
carry = result / 10;
result %= 10;
resultVect.insert(resultVect.begin(), result);
}
if (carry != 0) resultVect.insert(resultVect.begin(), carry);
return resultVect;
}
BigInt operator*(BigInt rhs)
{
int unitPlace = 0; // Keeps track of how many zeros to add in subsequent results
vector<char> totalVect; // Accumulated value after each addition
vector<char> resultVect; // Result of this particular multiplication
for (int i = rhs.storage.size() - 1; i >= 0; --i, unitPlace++)
{
int carry = 0;
for (int k = 0; k < unitPlace; ++k) resultVect.push_back(0);
for (int j = storage.size() - 1; j >= 0; j--)
{
int result = rhs.storage[i] * storage[j] + carry;
carry = result / 10;
result %= 10;
resultVect.insert(resultVect.begin(), result);
}
resultVect.insert(resultVect.begin(), carry);
totalVect = add(totalVect, resultVect); // Add sub-result
resultVect.clear();
}
// Strip leading zeros
for (int i = 0; i < totalVect.size(); ++i) {
if (totalVect[i] == 0) totalVect.erase(totalVect.begin() + i);
else break;
}
return BigInt{ totalVect };
}
};
int main()
{
BigInt a{ "335467" };
BigInt b{ "1019737" };
BigInt c = a * b;
std::cout << c.getAsString() << '\n';
cin.ignore();
return 0;
}
I've recently started learning C++, right now I'm working on a Matrix Class. I'm trying to overload operators and it turned out to be more difficult than I thought. So I've overloaded '=' and '+', first one works perfectly fine when I just want to set one matrix equal to another, but when I do something like 'matrix = matrix1 + matrix2' it crashes with no error. I'd be very thankful if someone helps me. Here's my code:
class Matrix
{
private:
int lines , columns;
int *Matrix_Numbers;
public:
Matrix();
Matrix(int n , int m)
{
lines = n , columns = m;
Matrix_Numbers = new int[lines * columns];
}
Matrix & operator = (Matrix &mat);
Matrix & operator + (Matrix &mat);
~Matrix()
{
delete Matrix_Numbers;
}
};
Matrix & Matrix::operator = (Matrix &mat)
{
this -> lines = mat.lines;
this -> columns = mat.columns;
int i , j;
for(i = 0 ; i < lines ; i++)
{
for(j = 0 ; j < columns ; j++)
{
this -> Matrix_Numbers[i * (this -> columns) + j] = mat(i , j);
}
}
return *this;
}
Matrix & Matrix::operator + (Matrix &mat)
{
Matrix result(lines , columns);
if(mat.lines == lines && mat.columns == columns)
{
int i , j;
for(i = 0 ; i < lines ; i++)
{
for(j = 0 ; j < columns ; j++)
{
result.Matrix_Numbers[i * columns + j] = Matrix_Numbers[i *
columns + j] + mat(i , j);
}
}
}
else
{
cout << "Error" << endl;
}
return result;
}
Of course it's just a part of my code, there's more, but I thought that this is the broken part. Let me know if you need more information:)
Your operator+ method returns a reference to the result. The only problem is that result is a local variable which means it gets destroyed upon the method returning. You should return it by value instead and let the compiler optimize stuff.
Like others pointed out in the comments, you should use const whenever possible so your operator+ can actually be called with constant parameters.
Beginner at C++ here. I specifically need help trying to figure out what is wrong with my overloaded * operator which is supposed to multiply two polynomials of a class Poly I made. My other overloaded operators appear to work just fine. Here is the original question:
P(x) = 2x4 + 3x3 – 12x2 + x – 19 (4th order polynomial)
or
P(x) = 2x7 + 5x5 – 7x2 + x – 19 (7th order polynomial)
Where the coefficients for the first and second equations can be described by the following array of integers
'Coeff1[ ] = {-19, 1, -12, 3, 2}'
'Coeff2[[ ] = {-19, 1, -7, 0, 0, 5, 0, 2}'
Design and code a polynomial class in C++ that has the following properties:
class Poly{
private:
int order; //order of the polynomial
int *coeff; // pointer to array of coeff on the heap
// size of coeff array predicated on (order + 1)
public:
Poly( ); //default constructor – order=0 & coeff[0] =1
Poly(int Order , int Default = 1) ;// creates Nth order poly
// and inits all coeffs
Poly(int Order, int *Coeff); //creates an Nth polynomial & inits
~Poly( ); // destructor
::::::: // copy constructor
//mutators & accessors
void set( ){// Query user for coefficient values);
void set(int coeff[ ], int size); // input coeffs via external coeff vector
int getOrder( )const; // get order of polynomial
int * get( ); //returns pointer to coeff array
//overloaded operators
Poly operator+( const Poly &rhs); // add two polynomials
Poly operator-( const Poly &rhs); // subt two polynomials
Poly operator*( const int scale); // scale a polynomial
Poly operator*(const Poly &rhs); // mult two polynomials
bool operator==(const Poly &rhs); // equality operator
const int & operator[ ](int I)const; // return the Ith coefficient
int & operator[ ](int I); // return the Ith coefficient
int operator( )(int X); // evaluate P(x) according
Poly & operator=(const Poly & rhs);
friend ostream & operator<<(ostream & Out, const Poly &rhs);
//other member functions
};
Demonstrate the following operations for the following Polynomials:
P1(x) = 2x4 + 3x3 – 12x2 + x – 19 (4th order polynomial)
P2(x) = 2x7 + 7x5 – 6x2 + x – 19 (7th order polynomial)
//display the following results for the polynomials defined above
o P3 = P1 + P2;
o P3 = P2 – P1;
o P3 = P1*10;
o P3 = 10*P1;
o P3 = P1*P2;
o bool flag = (P1==P2);
o P1[3] = P2[5]; // assign the 5th coefficient of P2 to 3rd coefficient of P1
o int Z = P1(int X = 5); // evaluate Polynomial for input X
// suggest using Horner’s method
o The displayed polynomial for P2 should be printed as follows
2X^7 + 7X^5 – 6X^2 + 1X – 1
Heres my code so far:
#include <iostream>
#include <cmath>
using namespace std;
class Poly
{
private:
int order;
int *coeff;
public:
Poly();
Poly(int Order, int Default=1);
Poly(int Order, int *Coeff);
Poly(const Poly ©);
~Poly();
void set(); //ask the user for the coefficient values
void set(int *Coeff, int size); //put the coefficient values in a external coeff vector
int getOrder() const; //gets the order of the polynomial
int* get() const; //returns pointer to coeff array
Poly operator +(const Poly &rhs);
Poly operator -(const Poly &rhs);
Poly operator *(const int scale);
Poly operator *(const Poly &rhs);
bool operator ==(const Poly &rhs);
const int & operator [](int access) const;
int & operator [](int access);
int operator ()(int X);
Poly & operator =(const Poly &rhs);
friend ostream & operator <<(ostream &Out, const Poly &rhs);
};
int main() {
int coeff1[] = {-19,1,-12,3,2};
int coeff2[] = {-19,1,-7,0,0,5,0,2};
Poly P1(4,coeff1);
Poly P2(7, coeff2);
Poly P3;
cout << "P1: " << P1 << endl;
cout << "P2: " << P2 << endl;
P3 = P1 * P2;
cout << "P1 * P2: " << P3 << endl;
return 0;
}
Poly::Poly() : order(0)
{
coeff = new int[1];
coeff[0] = 1;
}
Poly::Poly(int Order, int Default) : order(Order)
{
coeff = new int[order+1];
for (int i = 0; i < order+1; i++){
coeff[i] = Default;
}
}
Poly::Poly(int Order, int *Coeff) : order(Order), coeff(Coeff)
{
}
Poly::Poly(const Poly & copy)
{
order = copy.getOrder();
coeff = new int[order+1];
for (int i = 0; i < order+1; i++){
coeff[i] = copy.get()[i];
}
}
Poly::~Poly()
{
//if(coeff){
//delete [] coeff;
//}
}
void Poly::set()
{
cout << "Enter your coefficients:\n";
for (int i = 0; i < order+1; i++){
cin >> coeff[i];
}
}
void Poly::set(int *Coeff, int size)
{
delete [] coeff;
coeff = new int[size];
order = size;
for (int i = 0; i < order+1; i++){
coeff[i] = Coeff[i];
}
}
int Poly::getOrder() const
{
return order;
}
int* Poly::get() const
{
return coeff;
}
Poly Poly::operator +(const Poly &rhs)
{
int length = max(order+1, rhs.getOrder()+1);
int *answer = new int[length];
for (int i = 0; i < length + 1; i++){
answer[i] = coeff[i] + rhs.get()[i];
}
if (order > rhs.getOrder()){
for (int i = order+1 - rhs.getOrder()+1 ; i < order+1; i++){
answer[i] = coeff[i];
}
}
else if (order < rhs.getOrder()){
for (int i = rhs.getOrder()+1 - order+1; i < rhs.getOrder()+1; i++){
answer[i] = rhs.get()[i];
}
}
return Poly(length-1, answer);
}
Poly Poly::operator -(const Poly &rhs)
{
int length = max(order+1, rhs.getOrder()+1);
int *answer = new int[length];
for (int i = 0; i < order+1 && i < rhs.getOrder() + 1; i++){
answer[i] = coeff[i] - rhs.get()[i];
}
if (order > rhs.getOrder()){
for (int i = order+1-rhs.getOrder()+1; i < order+1; i++){
answer[i] = coeff[i];
}
}
else if (order < rhs.getOrder()){
for (int i = rhs.getOrder()+1 - order+1; i < rhs.getOrder()+1; i++){
answer[i] = 0 - rhs.get()[i];
}
}
return Poly(length-1, answer);
}
Poly Poly::operator *(const int scale)
{
int *answer = new int[order+1];
for (int i = 0; i < order+1; i++){
answer[i] = coeff[i] * scale;
}
return Poly(order, answer);
}
Poly Poly::operator *(const Poly &rhs)
{
int *shorter = NULL;
int *longer = NULL;
int s = 0;
int l = 0;
if(order < rhs.getOrder()){
shorter = coeff;
s = order;
longer = rhs.coeff;
l = rhs.order;
} else {
shorter = rhs.coeff;
s = rhs.order;
longer = coeff;
l = order;
}
Poly sum = Poly(l, longer) * shorter[0];
int *prod;
int nl;
for (int i = 1; i <= s; i++){
nl = l + i;
prod = new int[nl + 1];
for(int j = 0; j < i; j++){
prod[j] = 0;
}
for(int k = 0; k <= l; k++){
prod[k+i] = shorter[i] * longer[k];
}
sum = sum + Poly(nl, prod);
}
return sum;
}
bool Poly::operator ==(const Poly &rhs)
{
bool result;
if (order == rhs.order){
result = true;
for(int i = 0; i<order+1; i++){
if (coeff[i] != rhs.get()[i]){
result = false;
}
}
}else result = false;
return result;
}
const int& Poly::operator[](int access) const
{
return coeff[order + 1 - access];
}
int& Poly::operator [](int access)
{
return coeff[order + 1 - access];
}
int Poly::operator ()(int x)
{
int total = 0;
for(int i = 0; i < order + 1; i++){
total += coeff[i] * pow(x, i);
}
return total;
}
Poly &Poly::operator =(const Poly &rhs)
{
order = rhs.getOrder();
coeff = rhs.get();
return *this;
}
ostream& operator <<(ostream & Out, const Poly &rhs)
{
Out << rhs.get()[rhs.getOrder()] << "x^" << rhs.getOrder(); //first
for (int i = rhs.getOrder()-1; i > 0; i--){
if (rhs.get()[i] < 0 || rhs.get()[i] > 1) {
if(rhs.get()[i] > 0){
Out << " + ";
}
Out << rhs.get()[i] << "x^" << i << " ";
}else if (rhs.get()[i] == 1){
Out << "+ x ";
}else if (rhs.get()[i] == 1){
Out << "- x";
}
}
if (rhs.get()[rhs.getOrder() - rhs.getOrder()] > 0) {
Out << " + " << rhs.get()[rhs.getOrder() - rhs.getOrder()]; //last
}else Out << rhs.get()[rhs.getOrder() - rhs.getOrder()]; //last
Out << endl;
return Out;
}
`
Here is my current output. The answer I keep getting is half of the correct answer but I can't seem to get the first half.
P1: 2x^4 + 3x^3 -12x^2 + x -19
P2: 2x^7 + 5x^5 -7x^2 + x -19
P1 * P2: -114x^5 + 49x^4 -76x^3 + 362x^2 -38x^1 + 361
Any help is appreciated. Thank you
First, stop manually managing memory. Replace order and coeff with std::vector<int> values;. This bundles size() for order, and handles memory management for you.
If you don't know how to use std::vector yet, learn: it is far easier than learning how to write your own Poly class.
The next step in implementing Poly * Poly is to implement Poly& operator*=( Poly const& rhs );
The final step is friend Poly operator*( Poly lhs, Poly const& rhs ) { return std::move(lhs*=rhs); } There is little reason to use more than one line, and it can be inline.
That leaves operator*=.
The first step in implementing *= it so implement operator+(Poly const&, Poly const&), again via Poly& operator+=(Poly const&). As addition is easy, I will leave that to you.
The next step is scalar multiplication. Implement Poly& operator*=(int), and from it friend Poly operator*(Poly lhs, int x) { return std::move( lhs*=x ); } and friend Poly operator*(int x, Poly rhs) { return std::move( rhs*= x ); }. This is called 'scalar multiplication'.
Once we have those, *= becomes easy.
Store a copy of our initial value. (Poly init = std::move(*this);)
Create a return value (empty).
For each coefficient on the right hand side, do retval += coeff * init;
return *this = std::move(retval);
This is a sketch of the solution. To solve it really, you'll want to implement tests at each phase. Because I implemented *= in terms of other operations, testing each of those operations to make sure they work is key to having a debuggable *=. Then you test *=, then you test *, and then you are done.
If you are compiling in a compliant C++ compiler, a nice thing about using std::vector is that your default copy, move, assign and move-assign operations do the right thing, as does your default destructor. Seek to manage resources with specialized resource management classes, and follow The Rule of Zero, and you will have less pain.
Note that the above *= is not much easier to write than *, but in general *= is easier, so you should get into the habit anyhow.
Finally, note that this allocates more memory than is required, and is not optimal. It is, however, easy to get correct. After you have something like the above implemented, you can make it more optimal a number of ways. You can use karatsuba multiplication, you could use expression templates to avoid intermediate multiplication on the result += coeff * init; lines, you could reserve the right amount of space in result, or you could start playing with indexes manually.
The first step should be correctness, because if you have a correct algorithm you can at the very least use it to test your more optimal (trickier) algorithms.
Your code (for the polynomial multiplication) contains no comments and is rather opaque and hard to read/understand. So, I refuse to compile it (mentally) and can only guess, but it seems you don't know how multiplication of polynomials is defined, since your product polynomial is set to have order = min(order(A), order(B)) + 1, while correct is order(A)+order(B).
I suggest, you
1 make sure you understand polynomial multiplication before starting to code
2 write clear code with minimal instructions and useful comments (or better: useful variable names)
3 manage memory via the C++ standard library (using std::vector<>)
4 structure your code (write polynomial& polynomial::operator+=(polynomial const&) and then define the product as a standalone (can be a friend) via
polynomial operator*(polynomial const&a,polynomial const&b)
{
auto c=a;
c*=b;
return std::move(c);
}
though you may want to improve on this particular design (avoiding the re-allocation the is necessary in the above code in the c*=b operation).
I think this:
sum = sum + Poly(length, prod);
should be
sum = sum + Poly(length + i - 1, prod);
Also, the loop on i should stop at the shortest coeff array length.
Here's a modified version of the function:
Poly Poly::operator *(const Poly &rhs)
{
int *shorter = NULL;
int *longer = NULL;
int s = 0;
int l = 0;
if(order < rhs.order){
shorter = coeff;
s = order;
longer = rhs.coeff;
l = rhs.order;
} else {
shorter = rhs.coeff;
s = rhs.order;
longer = coeff;
l = order;
}
Poly sum = Poly(l, longer) * shorter[0];
int *prod;
int nl;
for (int i = 1; i <= s; i++){
nl = l + i;
prod = new int[nl + 1];
for(int j = 0; j < i; j++){
prod[j] = 0;
}
for(int k = 0; k <= l; k++){
prod[k+i] = shorter[i] * longer[k];
}
sum = sum + Poly(nl, prod);
}
return sum;
}
Note how it is based on order values rather than coeff array lengths (contrarily to the fix I indicated at the top of this answer).
If it doesn't work for you, then you may have other bugs in the code you didn't provide, or your algorithms work with array lengths, so you might have to adjust either to get things working.
Finally, as it has been said in other answers, you should use the tools provided by the standard library instead of handling array allocation by hand.
How can i store a big number in a variable and use a for loop?
I have a very big number 75472202764752234070123900087933251 and i need to loop from 0 to this number!
Is it even possible to do this? how much time will it take to end?
EDIT: i am trying to solve a hard problem by brute force. its a combination problem.the bruteforcing cases may reach 470C450.
so i guess i should use a different algorithm...
This might take
0.23 x 10^23 years if C++ processed 100,000 loops per second :|
http://www.wolframalpha.com/input/?i=75472202764752234070123900087933251%2F%28100000*1*3600*24*365%29
It looks that this number fits into 128 bit. So you could use a modern system and a modern compiler that implements such numbers. This would e.g be the case for a 64bit linux system with gcc as a compiler. This has something like __uint128_t that you could use.
Obviously you can't use such a variable as a for-loop variable, others have give you the calculations. But you could use it to store some of your calculations.
Well, you would need an implementation that can handle at least a subset of the initialization, boolean, and arithmetic functions on very large integers. Something like: https://mattmccutchen.net/bigint/.
For something that would give a bit better performance than a general large integer math library, you could use specialized operations specifically to allow use of a large integer as a counter. For an example of this, see dewtell's updated answer to this question.
As for it being possible for you to loop from 0 to that number: well, yes, it is possible to write the code for it with one of the above solutions, but I think the answer is no, you personally will not be able to do it because you will not be alive to see it finish.
[edit: Yes, I would definitely recommend you find a different algorithm. :D]
If you need to loop a certain number of times, and that number is greater than 2^64, just use while(1) because your computer will break before it counts up to 2^64 anyway.
There's no need for a complete bignum package - if all you need is a loop counter, here's a simple byte counter that uses an array of bytes as a counter. It stops when the byte array wraps around to all zeros again. If you wanted to count to some other value than 2^(bytesUsed*CHAR_BITS), you could just compute the two's complement value of the negative of the number of iterations you wanted, and let it count up to 0, keeping in mind that bytes[0] is the low-order byte (or use the positive value and count down instead of up).
#include <stdio.h>
#define MAXBYTES 20
/* Simple byte counter - note it uses argc as # of bytes to use for convenience */
int main(int argc, char **argv) {
unsigned char bytes[MAXBYTES];
const int bytesUsed = argc < MAXBYTES? argc : MAXBYTES;
int i;
unsigned long counter = (unsigned long)-1; /* to give loop something to do */
for (i = 0; i < bytesUsed; i++) bytes[i] = 0; /* Initialize bytes */
do {
for (i = 0; i < bytesUsed && !++bytes[i]; i++) ; /* NULL BODY - this is the byte counter */
counter++;
} while (i < bytesUsed);
printf("With %d bytes used, final counter value = %lu\n", bytesUsed, counter);
}
Run times for the first 4 values (under Cygwin, on a Lenovo T61):
$ time ./bytecounter
With 1 bytes used, final counter value = 255
real 0m0.078s
user 0m0.031s
sys 0m0.046s
$ time ./bytecounter a
With 2 bytes used, final counter value = 65535
real 0m0.063s
user 0m0.031s
sys 0m0.031s
$ time ./bytecounter a a
With 3 bytes used, final counter value = 16777215
real 0m0.125s
user 0m0.015s
sys 0m0.046s
$ time ./bytecounter a a a
With 4 bytes used, final counter value = 4294967295
real 0m6.578s
user 0m0.015s
sys 0m0.047s
At this rate, five bytes should take around half an hour, and six bytes should take the better part of a week. Of course the counter value will be inaccurate for those - it's mostly just there to verify the number of iterations for the smaller byte values and give the loop something to do.
Edit: And here's the time for five bytes, around half an hour as I predicted:
$ time ./bytecounter a a a a
With 5 bytes used, final counter value = 4294967295
real 27m22.184s
user 0m0.015s
sys 0m0.062s
Ok, here's code to take an arbitrary decimal number passed as the first arg and count down from it to zero. I set it up to allow the counter to use different size elements (just change the typedef for COUNTER_BASE), but it turns out that bytes are actually somewhat faster than either short or long on my system.
#include <stdio.h>
#include <limits.h> // defines CHAR_BIT
#include <ctype.h>
#include <vector>
using std::vector;
typedef unsigned char COUNTER_BASE;
typedef vector<COUNTER_BASE> COUNTER;
typedef vector<unsigned char> BYTEVEC;
const unsigned long byteMask = (~0ul) << CHAR_BIT;
const size_t MAXBYTES=20;
void mult10(BYTEVEC &val) {
// Multiply value by 10
unsigned int carry = 0;
int i;
for (i = 0; i < val.size(); i++) {
unsigned long value = val[i]*10ul+carry;
carry = (value & byteMask) >> CHAR_BIT;
val[i] = value & ~byteMask;
}
if (carry > 0) val.push_back(carry);
}
void addDigit(BYTEVEC &val, const char digit) {
// Add digit to the number in BYTEVEC.
unsigned int carry = digit - '0'; // Assumes ASCII char set
int i;
for (i = 0; i < val.size() && carry; i++) {
unsigned long value = static_cast<unsigned long>(val[i])+carry;
carry = (value & byteMask) >> CHAR_BIT;
val[i] = value & ~byteMask;
}
if (carry > 0) val.push_back(carry);
}
BYTEVEC Cstr2Bytevec(const char *str) {
// Turn a C-style string into a BYTEVEC. Only the digits in str apply,
// so that one can use commas, underscores, or other non-digits to separate
// digit groups.
BYTEVEC result;
result.reserve(MAXBYTES);
result[0]=0;
unsigned char *res=&result[0]; // For debugging
while (*str) {
if (isdigit(static_cast<int>(*str))) {
mult10(result);
addDigit(result, *str);
}
str++;
}
return result;
}
void packCounter(COUNTER &ctr, const BYTEVEC &val) {
// Pack the bytes from val into the (possibly larger) datatype of COUNTER
int i;
ctr.erase(ctr.begin(), ctr.end());
COUNTER_BASE value = 0;
for (i = 0; i < val.size(); i++) {
int pos = i%sizeof(COUNTER_BASE); // position of this byte in the value
if (i > 0 && pos == 0) {
ctr.push_back(value);
value = val[i];
} else {
value |= static_cast<COUNTER_BASE>(val[i]) << pos*CHAR_BIT;
}
}
ctr.push_back(value);
}
inline bool decrementAndTest(COUNTER &ctr) {
// decrement value in ctr and return true if old value was not all zeros
int i;
for (i = 0; i < ctr.size() && !(ctr[i]--); i++) ; // EMPTY BODY
return i < ctr.size();
}
inline bool decrementAndTest2(COUNTER_BASE *ctr, const size_t size) {
// decrement value in ctr and return true if old value was not all zeros
int i;
for (i = 0; i < size && !(ctr[i]--); i++) ; // EMPTY BODY
return i < size;
}
/* Vector counter - uses first arg (if supplied) as the count */
int main(int argc, const char *argv[]) {
BYTEVEC limit = Cstr2Bytevec(argc > 1? argv[1] : "0");
COUNTER ctr;
packCounter(ctr, limit);
COUNTER_BASE *ctr_vals = ctr.size() > 0 ? &ctr[0] : NULL;
size_t ctr_size = ctr.size();
unsigned long ul_counter = 0ul; /* to give loop something to do */
while(decrementAndTest2(ctr_vals, ctr_size)) {
ul_counter++;
};
printf("With %d bytes used, final ul_counter value = %lu\n", limit.size(), ul_counter);
return 0;
}
Examples of use:
$ time ./bigcounter 5
With 1 bytes used, final ul_counter value = 5
real 0m0.094s
user 0m0.031s
sys 0m0.047s
$ time ./bigcounter 5,000
With 2 bytes used, final ul_counter value = 5000
real 0m0.062s
user 0m0.015s
sys 0m0.062s
$ time ./bigcounter 5,000,000
With 3 bytes used, final ul_counter value = 5000000
real 0m0.093s
user 0m0.015s
sys 0m0.046s
$ time ./bigcounter 1,000,000,000
With 4 bytes used, final ul_counter value = 1000000000
real 0m2.688s
user 0m0.015s
sys 0m0.015s
$ time ./bigcounter 2,000,000,000
With 4 bytes used, final ul_counter value = 2000000000
real 0m5.125s
user 0m0.015s
sys 0m0.046s
$ time ./bigcounter 3,000,000,000
With 4 bytes used, final ul_counter value = 3000000000
real 0m7.485s
user 0m0.031s
sys 0m0.047s
$ time ./bigcounter 4,000,000,000
With 4 bytes used, final ul_counter value = 4000000000
real 0m9.875s
user 0m0.015s
sys 0m0.046s
$ time ./bigcounter 5,000,000,000
With 5 bytes used, final ul_counter value = 705032704
real 0m12.594s
user 0m0.046s
sys 0m0.015s
$ time ./bigcounter 6,000,000,000
With 5 bytes used, final ul_counter value = 1705032704
real 0m14.813s
user 0m0.015s
sys 0m0.062s
Unwrapping the counter vector into C-style data structures (i.e., using decrementAndTest2 instead of decrementAndTest) sped things up by around 20-25%, but the code is still about twice as slow as my previous C program for similar-sized examples (around 4 billion). This is with MS Visual C++ 6.0 as the compiler in release mode, optimizing for speed, on a 2GHz dual-core system, for both programs. Inlining the decrementAndTest2 function definitely makes a big difference (around 12 sec. vs. 30 for the 5 billion loop), but I'll have to see whether physically inlining the code as I did in the C program can get similar performance.
the variable in main function can Store even 100 factorial
#include <iostream>
#include <cstdio>
#include <vector>
#include <cstring>
#include <string>
#include <map>
#include <functional>
#include <algorithm>
#include <cstdlib>
#include <iomanip>
#include <stack>
#include <queue>
#include <deque>
#include <limits>
#include <cmath>
#include <numeric>
#include <set>
using namespace std;
//template for BIGINIT
// base and base_digits must be consistent
const int base = 10;
const int base_digits = 1;
struct bigint {
vector<int> a;
int sign;
bigint() :
sign(1) {
}
bigint(long long v) {
*this = v;
}
bigint(const string &s) {
read(s);
}
void operator=(const bigint &v) {
sign = v.sign;
a = v.a;
}
void operator=(long long v) {
sign = 1;
if (v < 0)
sign = -1, v = -v;
for (; v > 0; v = v / base)
a.push_back(v % base);
}
bigint operator+(const bigint &v) const {
if (sign == v.sign) {
bigint res = v;
for (int i = 0, carry = 0; i < (int) max(a.size(), v.a.size()) || carry; ++i) {
if (i == (int) res.a.size())
res.a.push_back(0);
res.a[i] += carry + (i < (int) a.size() ? a[i] : 0);
carry = res.a[i] >= base;
if (carry)
res.a[i] -= base;
}
return res;
}
return *this - (-v);
}
bigint operator-(const bigint &v) const {
if (sign == v.sign) {
if (abs() >= v.abs()) {
bigint res = *this;
for (int i = 0, carry = 0; i < (int) v.a.size() || carry; ++i) {
res.a[i] -= carry + (i < (int) v.a.size() ? v.a[i] : 0);
carry = res.a[i] < 0;
if (carry)
res.a[i] += base;
}
res.trim();
return res;
}
return -(v - *this);
}
return *this + (-v);
}
void operator*=(int v) {
if (v < 0)
sign = -sign, v = -v;
for (int i = 0, carry = 0; i < (int) a.size() || carry; ++i) {
if (i == (int) a.size())
a.push_back(0);
long long cur = a[i] * (long long) v + carry;
carry = (int) (cur / base);
a[i] = (int) (cur % base);
//asm("divl %%ecx" : "=a"(carry), "=d"(a[i]) : "A"(cur), "c"(base));
}
trim();
}
bigint operator*(int v) const {
bigint res = *this;
res *= v;
return res;
}
friend pair<bigint, bigint> divmod(const bigint &a1, const bigint &b1) {
int norm = base / (b1.a.back() + 1);
bigint a = a1.abs() * norm;
bigint b = b1.abs() * norm;
bigint q, r;
q.a.resize(a.a.size());
for (int i = a.a.size() - 1; i >= 0; i--) {
r *= base;
r += a.a[i];
int s1 = r.a.size() <= b.a.size() ? 0 : r.a[b.a.size()];
int s2 = r.a.size() <= b.a.size() - 1 ? 0 : r.a[b.a.size() - 1];
int d = ((long long) base * s1 + s2) / b.a.back();
r -= b * d;
while (r < 0)
r += b, --d;
q.a[i] = d;
}
q.sign = a1.sign * b1.sign;
r.sign = a1.sign;
q.trim();
r.trim();
return make_pair(q, r / norm);
}
bigint operator/(const bigint &v) const {
return divmod(*this, v).first;
}
bigint operator%(const bigint &v) const {
return divmod(*this, v).second;
}
void operator/=(int v) {
if (v < 0)
sign = -sign, v = -v;
for (int i = (int) a.size() - 1, rem = 0; i >= 0; --i) {
long long cur = a[i] + rem * (long long) base;
a[i] = (int) (cur / v);
rem = (int) (cur % v);
}
trim();
}
bigint operator/(int v) const {
bigint res = *this;
res /= v;
return res;
}
int operator%(int v) const {
if (v < 0)
v = -v;
int m = 0;
for (int i = a.size() - 1; i >= 0; --i)
m = (a[i] + m * (long long) base) % v;
return m * sign;
}
void operator+=(const bigint &v) {
*this = *this + v;
}
void operator-=(const bigint &v) {
*this = *this - v;
}
void operator*=(const bigint &v) {
*this = *this * v;
}
void operator/=(const bigint &v) {
*this = *this / v;
}
bool operator<(const bigint &v) const {
if (sign != v.sign)
return sign < v.sign;
if (a.size() != v.a.size())
return a.size() * sign < v.a.size() * v.sign;
for (int i = a.size() - 1; i >= 0; i--)
if (a[i] != v.a[i])
return a[i] * sign < v.a[i] * sign;
return false;
}
bool operator>(const bigint &v) const {
return v < *this;
}
bool operator<=(const bigint &v) const {
return !(v < *this);
}
bool operator>=(const bigint &v) const {
return !(*this < v);
}
bool operator==(const bigint &v) const {
return !(*this < v) && !(v < *this);
}
bool operator!=(const bigint &v) const {
return *this < v || v < *this;
}
void trim() {
while (!a.empty() && !a.back())
a.pop_back();
if (a.empty())
sign = 1;
}
bool isZero() const {
return a.empty() || (a.size() == 1 && !a[0]);
}
bigint operator-() const {
bigint res = *this;
res.sign = -sign;
return res;
}
bigint abs() const {
bigint res = *this;
res.sign *= res.sign;
return res;
}
long long longValue() const {
long long res = 0;
for (int i = a.size() - 1; i >= 0; i--)
res = res * base + a[i];
return res * sign;
}
friend bigint gcd(const bigint &a, const bigint &b) {
return b.isZero() ? a : gcd(b, a % b);
}
friend bigint lcm(const bigint &a, const bigint &b) {
return a / gcd(a, b) * b;
}
void read(const string &s) {
sign = 1;
a.clear();
int pos = 0;
while (pos < (int) s.size() && (s[pos] == '-' || s[pos] == '+')) {
if (s[pos] == '-')
sign = -sign;
++pos;
}
for (int i = s.size() - 1; i >= pos; i -= base_digits) {
int x = 0;
for (int j = max(pos, i - base_digits + 1); j <= i; j++)
x = x * 10 + s[j] - '0';
a.push_back(x);
}
trim();
}
friend istream& operator>>(istream &stream, bigint &v) {
string s;
stream >> s;
v.read(s);
return stream;
}
friend ostream& operator<<(ostream &stream, const bigint &v) {
if (v.sign == -1)
stream << '-';
stream << (v.a.empty() ? 0 : v.a.back());
for (int i = (int) v.a.size() - 2; i >= 0; --i)
stream << setw(base_digits) << setfill('0') << v.a[i];
return stream;
}
static vector<int> convert_base(const vector<int> &a, int old_digits, int new_digits) {
vector<long long> p(max(old_digits, new_digits) + 1);
p[0] = 1;
for (int i = 1; i < (int) p.size(); i++)
p[i] = p[i - 1] * 10;
vector<int> res;
long long cur = 0;
int cur_digits = 0;
for (int i = 0; i < (int) a.size(); i++) {
cur += a[i] * p[cur_digits];
cur_digits += old_digits;
while (cur_digits >= new_digits) {
res.push_back(int(cur % p[new_digits]));
cur /= p[new_digits];
cur_digits -= new_digits;
}
}
res.push_back((int) cur);
while (!res.empty() && !res.back())
res.pop_back();
return res;
}
typedef vector<long long> vll;
static vll karatsubaMultiply(const vll &a, const vll &b) {
int n = a.size();
vll res(n + n);
if (n <= 32) {
for (int i = 0; i < n; i++)
for (int j = 0; j < n; j++)
res[i + j] += a[i] * b[j];
return res;
}
int k = n >> 1;
vll a1(a.begin(), a.begin() + k);
vll a2(a.begin() + k, a.end());
vll b1(b.begin(), b.begin() + k);
vll b2(b.begin() + k, b.end());
vll a1b1 = karatsubaMultiply(a1, b1);
vll a2b2 = karatsubaMultiply(a2, b2);
for (int i = 0; i < k; i++)
a2[i] += a1[i];
for (int i = 0; i < k; i++)
b2[i] += b1[i];
vll r = karatsubaMultiply(a2, b2);
for (int i = 0; i < (int) a1b1.size(); i++)
r[i] -= a1b1[i];
for (int i = 0; i < (int) a2b2.size(); i++)
r[i] -= a2b2[i];
for (int i = 0; i < (int) r.size(); i++)
res[i + k] += r[i];
for (int i = 0; i < (int) a1b1.size(); i++)
res[i] += a1b1[i];
for (int i = 0; i < (int) a2b2.size(); i++)
res[i + n] += a2b2[i];
return res;
}
bigint operator*(const bigint &v) const {
vector<int> a6 = convert_base(this->a, base_digits, 6);
vector<int> b6 = convert_base(v.a, base_digits, 6);
vll a(a6.begin(), a6.end());
vll b(b6.begin(), b6.end());
while (a.size() < b.size())
a.push_back(0);
while (b.size() < a.size())
b.push_back(0);
while (a.size() & (a.size() - 1))
a.push_back(0), b.push_back(0);
vll c = karatsubaMultiply(a, b);
bigint res;
res.sign = sign * v.sign;
for (int i = 0, carry = 0; i < (int) c.size(); i++) {
long long cur = c[i] + carry;
res.a.push_back((int) (cur % 1000000));
carry = (int) (cur / 1000000);
}
res.a = convert_base(res.a, 6, base_digits);
res.trim();
return res;
}
};
//use : bigint var;
//template for biginit over
int main()
{
bigint var=10909000890789;
cout<<var;
return 0;
}
So I have been developing a polynomial class where a user inputs: 1x^0 + 2x^1 + 3x^2... and 1,2,3 (the coefficients) are stored in an int array
My overloaded + and - functions work, however, * doesnt work. No matter the input, it always shows -842150450
when is should be (5x^0 + x^1) * (-3x^0 + x^1) = -15x^0 + 2x^1 + 1x^2
or (x+5)(x-3) = x^2 +2x - 15
I'm using the overloaded * function like : Polynomial multiply = one * two;
Im guessing the problem is strtol(p, &endptr, 10) since it uses a long int, however, adding and subtracting works perfectly
My constructor
Polynomial::Polynomial(char *s)
{
char *string;
string = new char [strlen(s) + 1];
int length = strlen(string);
strcpy(string, s);
char *copy;
copy = new char [length];
strcpy(copy, string);
char *p = strtok(string, " +-");
counter = 0;
while (p)
{
p = strtok(NULL, " +-");
counter++;
}
coefficient = new int[counter];
p = strtok(copy, " +");
int a = 0;
while (p)
{
long int coeff;
char *endptr;
coeff = strtol(p, &endptr, 10); //stops at first non number
if (*p == 'x')
coeff = 1;
coefficient[a] = coeff;
p = strtok(NULL, " +");
a++;
}
}
and the overloaded * function
Polynomial Polynomial::operator * (const Polynomial &right)
{
Polynomial temp;
//make coefficient array
int count = (counter + right.counter) - 1;
temp.counter = count;
temp.coefficient = new int [count];
for (int i = 0; i < counter; i++)
{
for (int j = 0; j < right.counter; j++)
temp.coefficient[i+j] += coefficient[i] * right.coefficient[j];
}
return temp;
}
And heres my entire code: http://pastie.org/721143
You don't appear to initialise the temp.coefficient[i+j] to zero in your operator * ().
temp.coefficient = new int [count];
std::memset (temp.coefficient, 0, count * sizeof(int));
Convert -842150450 to hex to find back one of the magic values used in the CRT in the debug build. That helps finding the bug in your code:
temp.coefficient = new int [count];
// Must initialize the memory
for (int ix = 0; ix < count; ++ix) temp.coefficient[ix] = 0;
There are plenty other bugz btw, good luck fixing them.
Does
temp.coefficient = new int [count];
give you an array of zeroes?
Otherwise in your for loop you're adding stuff to garbage.
Replace
temp.coefficient = new int [count];
by
temp.coefficient = new int [count]();
in order to zero-initialize the array values.