From fe0c2b8517e17b30f10c24793112ac6817bca214 Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Fri, 1 May 2020 23:12:38 -0400 Subject: [PATCH 01/24] compute factorial of arbitrarily any number --- others/large_factorial.cpp | 128 +++++++++++++++++++++++++++++++++++++ 1 file changed, 128 insertions(+) create mode 100644 others/large_factorial.cpp diff --git a/others/large_factorial.cpp b/others/large_factorial.cpp new file mode 100644 index 000000000..ef9b68feb --- /dev/null +++ b/others/large_factorial.cpp @@ -0,0 +1,128 @@ +#include +#include +#include + +using namespace std; + +/** + * Store large unsigned numbers as a C++ vector + * The class provides convenience functions to add a + * digit to the number, perform multiplication of + * large number with long unsigned integers. + **/ +class large_number +{ +public: + large_number() /**< initializer */ + { + _digits.push_back(1); + } + + /** + * add a digit to the large number + **/ + void add_digit(unsigned int value) + { + if (value > 9) + { + fprintf(stderr, "digit > 9!!\n"); + exit(EXIT_FAILURE); + } + + _digits.push_back(value); + } + + /** + * Get number of digits in the number + **/ + const size_t num_digits() const + { + return _digits.size(); + } + + /** + * operator over load to access the + * i^th digit conveniently and also + * assign value to it + **/ + unsigned char &operator[](size_t n) + { + return this->_digits[n]; + } + + /** + * multiply large number with another integer and + * store the result in the same large number + **/ + void multiply(const unsigned long n) + { + size_t i; + unsigned long long carry = 0, temp; + for (i = 0; i < this->num_digits(); i++) + { + temp = (*this)[i] * n; + temp += carry; + if (temp < 10) + carry = 0; + else + { + carry = temp / 10; + temp = temp % 10; + } + (*this)[i] = temp; + } + + while (carry != 0) + { + this->add_digit(carry % 10); + carry /= 10; + } + }; + + /** + * print the large number + **/ + void print() + { + for (size_t i = num_digits(); i > 0; i--) + putchar(_digits[i - 1] + '0'); + }; + +private: + vector _digits; /**< where individual digits are stored */ +}; + +/** + * Main program + **/ +int main(int argc, char *argv[]) +{ + int number, i; + + //Asks for the number/position of term in Fibonnacci sequence + if (argc == 2) + number = atoi(argv[1]); + else + { + printf("Enter the value of n(n starts from 0 ): "); + scanf("%d", &number); + } + + large_number result; + + auto start_time = chrono::high_resolution_clock::now(); + for (i = 2; i <= number; i++) + /* Multiply every number from 2 thru N */ + result.multiply(i); + auto end_time = chrono::high_resolution_clock::now(); + chrono::duration time_taken = end_time - start_time; + + cout << number << "! = "; + result.print(); + cout << endl + << "Number of digits: " << result.num_digits() << endl + << "Time taken: " << time_taken.count() << " s" + << endl; + + return 0; +} From 70cd195f307c3e68e0779a9a0b95fd950f800489 Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Fri, 1 May 2020 23:31:39 -0400 Subject: [PATCH 02/24] large_factorial.cpp: added tests --- others/large_factorial.cpp | 67 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) diff --git a/others/large_factorial.cpp b/others/large_factorial.cpp index ef9b68feb..2e7d8bb66 100644 --- a/others/large_factorial.cpp +++ b/others/large_factorial.cpp @@ -92,6 +92,70 @@ private: vector _digits; /**< where individual digits are stored */ }; +bool test1() +{ + cout << "---- Check 1\t"; + unsigned int i, number = 10; + large_number result; + for (i = 2; i <= number; i++) + /* Multiply every number from 2 thru N */ + result.multiply(i); + + const char *known_reslt = "3628800"; + + /* check 1 */ + if (strlen(known_reslt) != result.num_digits()) + { + cerr << "Result lengths dont match! " << strlen(known_reslt) << " != " << result.num_digits() << endl; + return false; + } + + size_t N = result.num_digits(); + for (i = 0; i < N; i++) + { + if (known_reslt[i] != (result[N - i - 1] + '0')) + { + cerr << i << "^th digit mismatch! " << known_reslt[i] << " != " << result[N - i - 1] << endl; + return false; + } + } + + cout << "Passed!" << endl; + return true; +} + +bool test2() +{ + cout << "---- Check 2\t"; + unsigned int i, number = 100; + large_number result; + for (i = 2; i <= number; i++) + /* Multiply every number from 2 thru N */ + result.multiply(i); + + const char *known_reslt = "93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000"; + + /* check 1 */ + if (strlen(known_reslt) != result.num_digits()) + { + cerr << "Result lengths dont match! " << strlen(known_reslt) << " != " << result.num_digits() << endl; + return false; + } + + size_t N = result.num_digits(); + for (i = 0; i < N; i++) + { + if (known_reslt[i] != (result[N - i - 1] + '0')) + { + cerr << i << "^th digit mismatch! " << known_reslt[i] << " != " << result[N - i - 1] << endl; + return false; + } + } + + cout << "Passed!" << endl; + return true; +} + /** * Main program **/ @@ -124,5 +188,8 @@ int main(int argc, char *argv[]) << "Time taken: " << time_taken.count() << " s" << endl; + test1(); + test2(); + return 0; } From a1997776c93904f0f4d66c1a802cd1429975bcf2 Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Sat, 2 May 2020 15:57:12 -0400 Subject: [PATCH 03/24] split large_number class to a separate header file --- others/large_factorial.cpp | 114 ++----------- others/large_number.h | 323 +++++++++++++++++++++++++++++++++++++ 2 files changed, 336 insertions(+), 101 deletions(-) create mode 100644 others/large_number.h diff --git a/others/large_factorial.cpp b/others/large_factorial.cpp index 2e7d8bb66..dccdcaeab 100644 --- a/others/large_factorial.cpp +++ b/others/large_factorial.cpp @@ -1,97 +1,10 @@ #include +#include #include -#include +#include "large_number.h" using namespace std; -/** - * Store large unsigned numbers as a C++ vector - * The class provides convenience functions to add a - * digit to the number, perform multiplication of - * large number with long unsigned integers. - **/ -class large_number -{ -public: - large_number() /**< initializer */ - { - _digits.push_back(1); - } - - /** - * add a digit to the large number - **/ - void add_digit(unsigned int value) - { - if (value > 9) - { - fprintf(stderr, "digit > 9!!\n"); - exit(EXIT_FAILURE); - } - - _digits.push_back(value); - } - - /** - * Get number of digits in the number - **/ - const size_t num_digits() const - { - return _digits.size(); - } - - /** - * operator over load to access the - * i^th digit conveniently and also - * assign value to it - **/ - unsigned char &operator[](size_t n) - { - return this->_digits[n]; - } - - /** - * multiply large number with another integer and - * store the result in the same large number - **/ - void multiply(const unsigned long n) - { - size_t i; - unsigned long long carry = 0, temp; - for (i = 0; i < this->num_digits(); i++) - { - temp = (*this)[i] * n; - temp += carry; - if (temp < 10) - carry = 0; - else - { - carry = temp / 10; - temp = temp % 10; - } - (*this)[i] = temp; - } - - while (carry != 0) - { - this->add_digit(carry % 10); - carry /= 10; - } - }; - - /** - * print the large number - **/ - void print() - { - for (size_t i = num_digits(); i > 0; i--) - putchar(_digits[i - 1] + '0'); - }; - -private: - vector _digits; /**< where individual digits are stored */ -}; - bool test1() { cout << "---- Check 1\t"; @@ -99,7 +12,7 @@ bool test1() large_number result; for (i = 2; i <= number; i++) /* Multiply every number from 2 thru N */ - result.multiply(i); + result *= i; const char *known_reslt = "3628800"; @@ -110,12 +23,12 @@ bool test1() return false; } - size_t N = result.num_digits(); + const size_t N = result.num_digits(); for (i = 0; i < N; i++) { - if (known_reslt[i] != (result[N - i - 1] + '0')) + if (known_reslt[i] != result.digit_char(i)) { - cerr << i << "^th digit mismatch! " << known_reslt[i] << " != " << result[N - i - 1] << endl; + cerr << i << "^th digit mismatch! " << known_reslt[i] << " != " << result.digit_char(i) << endl; return false; } } @@ -131,7 +44,7 @@ bool test2() large_number result; for (i = 2; i <= number; i++) /* Multiply every number from 2 thru N */ - result.multiply(i); + result *= i; const char *known_reslt = "93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000"; @@ -142,12 +55,12 @@ bool test2() return false; } - size_t N = result.num_digits(); + const size_t N = result.num_digits(); for (i = 0; i < N; i++) { - if (known_reslt[i] != (result[N - i - 1] + '0')) + if (known_reslt[i] != result.digit_char(i)) { - cerr << i << "^th digit mismatch! " << known_reslt[i] << " != " << result[N - i - 1] << endl; + cerr << i << "^th digit mismatch! " << known_reslt[i] << " != " << result.digit_char(i) << endl; return false; } } @@ -177,19 +90,18 @@ int main(int argc, char *argv[]) auto start_time = chrono::high_resolution_clock::now(); for (i = 2; i <= number; i++) /* Multiply every number from 2 thru N */ - result.multiply(i); + result *= i; auto end_time = chrono::high_resolution_clock::now(); chrono::duration time_taken = end_time - start_time; - cout << number << "! = "; - result.print(); - cout << endl + cout << number << "! = " << result << endl << "Number of digits: " << result.num_digits() << endl << "Time taken: " << time_taken.count() << " s" << endl; test1(); test2(); + result.test(); return 0; } diff --git a/others/large_number.h b/others/large_number.h new file mode 100644 index 000000000..0494a540b --- /dev/null +++ b/others/large_number.h @@ -0,0 +1,323 @@ +/** + * @author Krishna Vedala + * @email krishna (dot) vedala (at) ieee (dot) org + **/ + +#ifndef __LARGE_NUMBER__ +#define __LARGE_NUMBER__ +#include +#include +#include +#include + +/** + * Store large unsigned numbers as a C++ vector + * The class provides convenience functions to add a + * digit to the number, perform multiplication of + * large number with long unsigned integers. + **/ +class large_number +{ +public: + large_number() /**< initializer */ + { + _digits.push_back(1); + } + + large_number(unsigned long n) /**< initializer */ + { + unsigned long carry = n; + do + { + add_digit(carry % 10); + carry /= 10; + } while (carry != 0); + } + + large_number(const large_number &a) /**< initializer */ + { + _digits = a._digits; + } + + large_number(const std::vector &vec) /**< initializer */ + { + _digits = vec; + } + + /** + * Function to check implementation + **/ + static bool test() + { + std::cout << "------ Checking `large_number` class implementations\t" << std::endl; + large_number a(40); + a *= 10; + if (a != large_number(400)) + { + std::cerr << "\tFailed 1/5 (" << a << "!=400)" << std::endl; + return false; + } + std::cout << "\tPassed 1/5..."; + a += 120; + if (a != large_number(520)) + { + std::cerr << "\tFailed 2/5 (" << a << "!=520)" << std::endl; + return false; + } + std::cout << "\tPassed 2/5..."; + a *= 10; + if (a != large_number(5200)) + { + std::cerr << "\tFailed 3/5 (" << a << "!=5200)" << std::endl; + return false; + } + std::cout << "\tPassed 3/5..."; + ++a; + if (a != large_number(5201)) + { + std::cerr << "\tFailed 4/5 (" << a << "!=5201)" << std::endl; + return false; + } + std::cout << "\tPassed 4/5..."; + a++; + if (a != large_number(5202)) + { + std::cerr << "\tFailed 5/5 (" << a << "!=5202)" << std::endl; + return false; + } + std::cout << "\tPassed 5/5..." << std::endl; + return true; + } + + /** + * add a digit at MSB to the large number + **/ + void add_digit(unsigned int value) + { + if (value > 9) + { + std::cerr << "digit > 9!!\n"; + exit(EXIT_FAILURE); + } + + _digits.push_back(value); + } + + /** + * Get number of digits in the number + **/ + const size_t num_digits() const + { + return _digits.size(); + } + + /** + * operator over load to access the + * i^th digit conveniently and also + * assign value to it + **/ + inline unsigned char &operator[](size_t n) + { + return this->_digits[n]; + } + + inline const unsigned char &operator[](size_t n) const + { + return this->_digits[n]; + } + + /** + * operator overload to compare two numbers + **/ + friend std::ostream &operator<<(std::ostream &out, const large_number &a) + { + for (size_t i = a.num_digits(); i > 0; i--) + out << a[i - 1] + '0'; + return out; + } + + /** + * operator overload to compare two numbers + **/ + friend bool operator==(const large_number &a, const large_number b) + { + size_t N = a.num_digits(); + if (N != b.num_digits()) + return false; + for (size_t i = 0; i < N; i++) + if (a[i] != b[i]) + return false; + return true; + } + + /** + * operator overload to compare two numbers + **/ + friend bool operator!=(const large_number &a, const large_number b) + { + return !(a == b); + } + + /** + * operator overload to increment (prefix) + **/ + large_number &operator++() + { + this->add((unsigned int)1); + return *this; + } + + /** + * operator overload to increment (postfix) + **/ + large_number &operator++(int) + { + large_number tmp(_digits); + ++(*this); + return tmp; + } + + /** + * operator overload to add + **/ + template + large_number &operator+=(T &n) + { + if (std::is_same::value) // if adding with another large_number + { + large_number *b = &n; + const size_t max_L = std::max(this->num_digits(), b->num_digits()); + unsigned int carry = 0, temp; + for (size_t i = 0; i < max_L; i++) + { + temp += carry; + if (i < b->num_digits()) + temp += (*b)[i]; + if (i < this->num_digits()) + temp += (*this)[i]; + if (temp < 10) + carry = 0; + else + { + carry = temp / 10; + temp = temp % 10; + } + if (i < this->num_digits()) + (*this)[i] = temp; + else + this->add_digit(temp); + } + while (carry != 0) + { + if (i < this->num_digits()) + (*this)[i] = carry % 10; + else + this->add_digit(carry % 10); + carry /= 10; + } + + return *this; + } + + static_assert(std::is_integral::value, "Must be integer addition unsigned integer types."); + // typedef typename std::make_unsigned::type T2; + this->add(b); + return *this; + } + + // /** + // * operator overload to increment + // **/ + // friend large_number &operator+(large_number a, const large_number b) + // { + // const size_t max_L = std::max(a.num_digits(), b.num_digits()); + + // return a; + // } + + /** + * operator overload to increment + **/ + template + large_number &operator*=(const T n) + { + static_assert(std::is_integral::value, "Must be integer addition unsigned integer types."); + this->multiply(n); + return *this; + } + + /** + * returns i^th digit as an ASCII character + **/ + const char digit_char(size_t i) const + { + return _digits[num_digits() - i - 1] + '0'; + } + +private: + /** + * multiply large number with another integer and + * store the result in the same large number + **/ + template + void multiply(const T n) + { + static_assert(std::is_integral::value, "Can only have integer types."); + // assert(!(std::is_signed::value)); //, "Implemented only for unsigned integer types."); + + size_t i; + unsigned long long carry = 0, temp; + for (i = 0; i < this->num_digits(); i++) + { + temp = (*this)[i] * n; + temp += carry; + if (temp < 10) + carry = 0; + else + { + carry = temp / 10; + temp = temp % 10; + } + (*this)[i] = temp; + } + + while (carry != 0) + { + this->add_digit(carry % 10); + carry /= 10; + } + }; + + /** + * add large number with another integer and + * store the result in the same large number + **/ + template + void add(const T n) + { + static_assert(std::is_integral::value, "Can only have integer types."); + // static_assert(!(std::is_signed::value), "Implemented only for unsigned integer types."); + + size_t i = 0; + long long carry = n; + + while (carry != 0) + { + if (i < this->num_digits()) + { + carry += (*this)[i]; + (*this)[i] = carry % 10; + i++; + } + else + this->add_digit(carry % 10); + carry /= 10; + if (carry == 0) + return; + } + }; + + std::vector _digits; /**< where individual digits are stored */ +}; + +#endif From 72ac15ed01dfd3064616a87053adfe7b2073f18e Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Sat, 2 May 2020 17:19:43 -0400 Subject: [PATCH 04/24] resolved compiler warnings --- others/large_number.h | 145 +++++++++++++++++------------------------- 1 file changed, 60 insertions(+), 85 deletions(-) diff --git a/others/large_number.h b/others/large_number.h index 0494a540b..6d117d9dd 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -8,6 +8,7 @@ #include #include #include +#include #include /** @@ -19,12 +20,12 @@ class large_number { public: - large_number() /**< initializer */ + large_number() /**< initializer with value = 1 */ { _digits.push_back(1); } - large_number(unsigned long n) /**< initializer */ + large_number(unsigned long n) /**< initializer from an integer */ { unsigned long carry = n; do @@ -34,16 +35,22 @@ public: } while (carry != 0); } - large_number(const large_number &a) /**< initializer */ + large_number(const large_number &a) /**< initializer from another large_number */ { _digits = a._digits; } - large_number(const std::vector &vec) /**< initializer */ + large_number(const std::vector &vec) /**< initializer from a vector */ { _digits = vec; } + large_number(const char *number_str) /**< initializer from a string */ + { + for (size_t i = strlen(number_str); i > 0; i--) + _digits.push_back(number_str[i - 1] - '0'); + } + /** * Function to check implementation **/ @@ -51,41 +58,54 @@ public: { std::cout << "------ Checking `large_number` class implementations\t" << std::endl; large_number a(40); + // 1. test multiplication a *= 10; if (a != large_number(400)) { - std::cerr << "\tFailed 1/5 (" << a << "!=400)" << std::endl; + std::cerr << "\tFailed 1/6 (" << a << "!=400)" << std::endl; return false; } - std::cout << "\tPassed 1/5..."; + std::cout << "\tPassed 1/6..."; + // 2. test compound addition with integer a += 120; if (a != large_number(520)) { - std::cerr << "\tFailed 2/5 (" << a << "!=520)" << std::endl; + std::cerr << "\tFailed 2/6 (" << a << "!=520)" << std::endl; return false; } - std::cout << "\tPassed 2/5..."; + std::cout << "\tPassed 2/6..."; + // 3. test compound multiplication again a *= 10; if (a != large_number(5200)) { - std::cerr << "\tFailed 3/5 (" << a << "!=5200)" << std::endl; + std::cerr << "\tFailed 3/6 (" << a << "!=5200)" << std::endl; return false; } - std::cout << "\tPassed 3/5..."; + std::cout << "\tPassed 3/6..."; + // 4. test increment (prefix) ++a; if (a != large_number(5201)) { - std::cerr << "\tFailed 4/5 (" << a << "!=5201)" << std::endl; + std::cerr << "\tFailed 4/6 (" << a << "!=5201)" << std::endl; return false; } - std::cout << "\tPassed 4/5..."; + std::cout << "\tPassed 4/6..."; + // 5. test increment (postfix) a++; if (a != large_number(5202)) { - std::cerr << "\tFailed 5/5 (" << a << "!=5202)" << std::endl; + std::cerr << "\tFailed 5/6 (" << a << "!=5202)" << std::endl; return false; } - std::cout << "\tPassed 5/5..." << std::endl; + std::cout << "\tPassed 5/6..."; + // 6. test addition with another large number + a = a + large_number("7000000000000000000000000000000"); + if (a != large_number("7000000000000000000000000005202")) + { + std::cerr << "\tFailed 6/6 (" << a << "!=7000000000000000000000000005202)" << std::endl; + return false; + } + std::cout << "\tPassed 6/6..." << std::endl; return true; } @@ -132,14 +152,14 @@ public: friend std::ostream &operator<<(std::ostream &out, const large_number &a) { for (size_t i = a.num_digits(); i > 0; i--) - out << a[i - 1] + '0'; + out << static_cast(a[i - 1]); return out; } /** * operator overload to compare two numbers **/ - friend bool operator==(const large_number &a, const large_number b) + friend bool operator==(const large_number &a, const large_number &b) { size_t N = a.num_digits(); if (N != b.num_digits()) @@ -153,7 +173,7 @@ public: /** * operator overload to compare two numbers **/ - friend bool operator!=(const large_number &a, const large_number b) + friend bool operator!=(const large_number &a, const large_number &b) { return !(a == b); } @@ -163,14 +183,14 @@ public: **/ large_number &operator++() { - this->add((unsigned int)1); + (*this) += 1; return *this; } /** * operator overload to increment (postfix) **/ - large_number &operator++(int) + large_number operator++(int) { large_number tmp(_digits); ++(*this); @@ -181,59 +201,43 @@ public: * operator overload to add **/ template - large_number &operator+=(T &n) + large_number &operator+=(T n) { - if (std::is_same::value) // if adding with another large_number + if (typeid(T) == typeid(large_number)) // if adding with another large_number { - large_number *b = &n; + large_number *b = (large_number *)&n; const size_t max_L = std::max(this->num_digits(), b->num_digits()); - unsigned int carry = 0, temp; - for (size_t i = 0; i < max_L; i++) + unsigned int carry = 0; + size_t i; + for (i = 0; i < max_L || carry != 0; i++) { - temp += carry; if (i < b->num_digits()) - temp += (*b)[i]; + carry += (*b)[i]; if (i < this->num_digits()) - temp += (*this)[i]; - if (temp < 10) - carry = 0; - else - { - carry = temp / 10; - temp = temp % 10; - } - if (i < this->num_digits()) - (*this)[i] = temp; - else - this->add_digit(temp); - } - while (carry != 0) - { + carry += (*this)[i]; if (i < this->num_digits()) (*this)[i] = carry % 10; else this->add_digit(carry % 10); carry /= 10; } - - return *this; } - - static_assert(std::is_integral::value, "Must be integer addition unsigned integer types."); - // typedef typename std::make_unsigned::type T2; - this->add(b); + else if (std::is_integral::value) + return (*this) += large_number(n); + else + std::cerr << "Must be integer addition unsigned integer types." << std::endl; return *this; } - // /** - // * operator overload to increment - // **/ - // friend large_number &operator+(large_number a, const large_number b) - // { - // const size_t max_L = std::max(a.num_digits(), b.num_digits()); - - // return a; - // } + /** + * operator overload to perform addition + **/ + template + friend large_number &operator+(large_number &a, const T &b) + { + a += b; + return a; + } /** * operator overload to increment @@ -288,35 +292,6 @@ private: } }; - /** - * add large number with another integer and - * store the result in the same large number - **/ - template - void add(const T n) - { - static_assert(std::is_integral::value, "Can only have integer types."); - // static_assert(!(std::is_signed::value), "Implemented only for unsigned integer types."); - - size_t i = 0; - long long carry = n; - - while (carry != 0) - { - if (i < this->num_digits()) - { - carry += (*this)[i]; - (*this)[i] = carry % 10; - i++; - } - else - this->add_digit(carry % 10); - carry /= 10; - if (carry == 0) - return; - } - }; - std::vector _digits; /**< where individual digits are stored */ }; From 1cb1641abc35fed7143c6d4ec7af8739bc056810 Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Sat, 2 May 2020 17:56:19 -0400 Subject: [PATCH 05/24] compute arbitrarily large fibonacci number --- others/fibonacci_large.cpp | 51 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 51 insertions(+) create mode 100644 others/fibonacci_large.cpp diff --git a/others/fibonacci_large.cpp b/others/fibonacci_large.cpp new file mode 100644 index 000000000..709268b66 --- /dev/null +++ b/others/fibonacci_large.cpp @@ -0,0 +1,51 @@ +/** + * Computes N^th Fibonacci number given as + * input argument. Uses custom build arbitrary integers library + * to perform additions and other operations. + * + * Took 0.608246 seconds to compute 50,000^th Fibonacci + * number that contains 10450 digits! + **/ + +#include "large_number.h" +#include +#include + +large_number fib(unsigned long long n) +{ + large_number f0(1); + large_number f1(1); + + do + { + large_number f2 = f0 + f1; + f0 = f1; + f1 = f2; + n--; + } while (n > 2); // since we start from 2 + return f1; +} + +int main(int argc, char *argv[]) +{ + unsigned long long N; + if (argc == 2) + N = strtoull(argv[1], NULL, 10); + else + { + std::cout << "Enter N: "; + std::cin >> N; + } + + auto start_time = std::chrono::high_resolution_clock::now(); + large_number result = fib(N); + auto end_time = std::chrono::high_resolution_clock::now(); + std::chrono::duration time_taken = end_time - start_time; + + std::cout + << std::endl + << N << "^th Fibonacci number: " << result << std::endl + << "Number of digits: " << result.num_digits() << std::endl + << "Time taken: " << time_taken.count() << " s" << std::endl; + return 0; +} \ No newline at end of file From f4778612e071ee5c1502ab736ed822b8b81b2678 Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Sat, 2 May 2020 17:56:42 -0400 Subject: [PATCH 06/24] large_number: created assignment operator --- others/large_number.h | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/others/large_number.h b/others/large_number.h index 6d117d9dd..8a6afcaa4 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -239,6 +239,14 @@ public: return a; } + /** + * assignment operator + **/ + void operator=(const large_number &b) + { + _digits = b._digits; + } + /** * operator overload to increment **/ From 9b538f3783415e7172a5372800ea965dc911b7ba Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Sat, 2 May 2020 18:04:58 -0400 Subject: [PATCH 07/24] ignore non numeric characters when creating large_number from a string --- others/large_number.h | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/others/large_number.h b/others/large_number.h index 8a6afcaa4..8c7f688d0 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -48,7 +48,11 @@ public: large_number(const char *number_str) /**< initializer from a string */ { for (size_t i = strlen(number_str); i > 0; i--) - _digits.push_back(number_str[i - 1] - '0'); + { + unsigned char a = number_str[i - 1] - '0'; + if (a >= 0 && a <= 9) + _digits.push_back(a); + } } /** From 9c633857bd396bbf490ad8e736832f31ca4caced Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Sat, 2 May 2020 18:05:11 -0400 Subject: [PATCH 08/24] added test case --- others/fibonacci_large.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/others/fibonacci_large.cpp b/others/fibonacci_large.cpp index 709268b66..a47e967d3 100644 --- a/others/fibonacci_large.cpp +++ b/others/fibonacci_large.cpp @@ -47,5 +47,11 @@ int main(int argc, char *argv[]) << N << "^th Fibonacci number: " << result << std::endl << "Number of digits: " << result.num_digits() << std::endl << "Time taken: " << time_taken.count() << " s" << std::endl; + + if (fib(5000) == large_number("3878968454388325633701916308325905312082127714646245106160597214895550139044037097010822916462210669479293452858882973813483102008954982940361430156911478938364216563944106910214505634133706558656238254656700712525929903854933813928836378347518908762970712033337052923107693008518093849801803847813996748881765554653788291644268912980384613778969021502293082475666346224923071883324803280375039130352903304505842701147635242270210934637699104006714174883298422891491273104054328753298044273676822977244987749874555691907703880637046832794811358973739993110106219308149018570815397854379195305617510761053075688783766033667355445258844886241619210553457493675897849027988234351023599844663934853256411952221859563060475364645470760330902420806382584929156452876291575759142343809142302917491088984155209854432486594079793571316841692868039545309545388698114665082066862897420639323438488465240988742395873801976993820317174208932265468879364002630797780058759129671389634214252579116872755600360311370547754724604639987588046985178408674382863125")) + std::cout << "Test for 5000^th Fibonacci number passed!" << std::endl; + else + std::cerr << "Test for 5000^th Fibonacci number failed!" << std::endl; + return 0; } \ No newline at end of file From 90840a1e3747ce65fb4c557ce6f13ee51f30d416 Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Sat, 2 May 2020 18:06:41 -0400 Subject: [PATCH 09/24] user editable test "N" --- others/fibonacci_large.cpp | 7 ++++--- 1 file changed, 4 insertions(+), 3 deletions(-) diff --git a/others/fibonacci_large.cpp b/others/fibonacci_large.cpp index a47e967d3..12b926759 100644 --- a/others/fibonacci_large.cpp +++ b/others/fibonacci_large.cpp @@ -48,10 +48,11 @@ int main(int argc, char *argv[]) << "Number of digits: " << result.num_digits() << std::endl << "Time taken: " << time_taken.count() << " s" << std::endl; - if (fib(5000) == large_number("3878968454388325633701916308325905312082127714646245106160597214895550139044037097010822916462210669479293452858882973813483102008954982940361430156911478938364216563944106910214505634133706558656238254656700712525929903854933813928836378347518908762970712033337052923107693008518093849801803847813996748881765554653788291644268912980384613778969021502293082475666346224923071883324803280375039130352903304505842701147635242270210934637699104006714174883298422891491273104054328753298044273676822977244987749874555691907703880637046832794811358973739993110106219308149018570815397854379195305617510761053075688783766033667355445258844886241619210553457493675897849027988234351023599844663934853256411952221859563060475364645470760330902420806382584929156452876291575759142343809142302917491088984155209854432486594079793571316841692868039545309545388698114665082066862897420639323438488465240988742395873801976993820317174208932265468879364002630797780058759129671389634214252579116872755600360311370547754724604639987588046985178408674382863125")) - std::cout << "Test for 5000^th Fibonacci number passed!" << std::endl; + N = 5000; + if (fib(N) == large_number("3878968454388325633701916308325905312082127714646245106160597214895550139044037097010822916462210669479293452858882973813483102008954982940361430156911478938364216563944106910214505634133706558656238254656700712525929903854933813928836378347518908762970712033337052923107693008518093849801803847813996748881765554653788291644268912980384613778969021502293082475666346224923071883324803280375039130352903304505842701147635242270210934637699104006714174883298422891491273104054328753298044273676822977244987749874555691907703880637046832794811358973739993110106219308149018570815397854379195305617510761053075688783766033667355445258844886241619210553457493675897849027988234351023599844663934853256411952221859563060475364645470760330902420806382584929156452876291575759142343809142302917491088984155209854432486594079793571316841692868039545309545388698114665082066862897420639323438488465240988742395873801976993820317174208932265468879364002630797780058759129671389634214252579116872755600360311370547754724604639987588046985178408674382863125")) + std::cout << "Test for " << N << "^th Fibonacci number passed!" << std::endl; else - std::cerr << "Test for 5000^th Fibonacci number failed!" << std::endl; + std::cerr << "Test for " << N << "^th Fibonacci number failed!" << std::endl; return 0; } \ No newline at end of file From f1b07d33a7e47921862b9702a35f6d2d1007c099 Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Sat, 2 May 2020 18:10:15 -0400 Subject: [PATCH 10/24] remove incorrect comment --- others/large_factorial.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/others/large_factorial.cpp b/others/large_factorial.cpp index dccdcaeab..5ee116b4c 100644 --- a/others/large_factorial.cpp +++ b/others/large_factorial.cpp @@ -76,7 +76,6 @@ int main(int argc, char *argv[]) { int number, i; - //Asks for the number/position of term in Fibonnacci sequence if (argc == 2) number = atoi(argv[1]); else From a77151c254d6c820b4af9984814b8cb6d77b1df1 Mon Sep 17 00:00:00 2001 From: github-actions <${GITHUB_ACTOR}@users.noreply.github.com> Date: Sun, 24 May 2020 18:38:16 +0000 Subject: [PATCH 11/24] updating DIRECTORY.md --- DIRECTORY.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/DIRECTORY.md b/DIRECTORY.md index ddbfd06d8..d7c138621 100644 --- a/DIRECTORY.md +++ b/DIRECTORY.md @@ -137,8 +137,11 @@ * [Decimal To Roman Numeral](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/Decimal%20to%20Roman%20Numeral.cpp) * [Fast Interger Input](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/fast_interger_input.cpp) * [Fibonacci](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/fibonacci.cpp) + * [Fibonacci Large](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/fibonacci_large.cpp) * [Gcd Of N Numbers](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/GCD_of_n_numbers.cpp) * [Happy Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/happy_number.cpp) + * [Large Factorial](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/large_factorial.cpp) + * [Large Number](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/large_number.h) * [Matrix Exponentiation](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/matrix_exponentiation.cpp) * [Measure Time Elapsed](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/measure_time_elapsed.cpp) * [Palindromeofnumber](https://github.com/TheAlgorithms/C-Plus-Plus/blob/master/others/Palindromeofnumber.cpp) From 236b6581302989cc5770233ec0ed6c58db621642 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sun, 24 May 2020 15:56:45 -0400 Subject: [PATCH 12/24] replace `std::chronos` with `ctime` - cpplint does not allow c++-11 --- others/fibonacci_large.cpp | 61 +++++++++------ others/large_factorial.cpp | 91 +++++++++++----------- others/large_number.h | 152 +++++++++++++++---------------------- 3 files changed, 142 insertions(+), 162 deletions(-) diff --git a/others/fibonacci_large.cpp b/others/fibonacci_large.cpp index 12b926759..bdfb201a5 100644 --- a/others/fibonacci_large.cpp +++ b/others/fibonacci_large.cpp @@ -7,52 +7,69 @@ * number that contains 10450 digits! **/ -#include "large_number.h" +#include #include -#include -large_number fib(unsigned long long n) -{ +#include "large_number.h" + +large_number fib(unsigned long long n) { large_number f0(1); large_number f1(1); - do - { + do { large_number f2 = f0 + f1; f0 = f1; f1 = f2; n--; - } while (n > 2); // since we start from 2 + } while (n > 2); // since we start from 2 return f1; } -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { unsigned long long N; if (argc == 2) N = strtoull(argv[1], NULL, 10); - else - { + else { std::cout << "Enter N: "; std::cin >> N; } - auto start_time = std::chrono::high_resolution_clock::now(); + clock_t start_time = std::clock(); large_number result = fib(N); - auto end_time = std::chrono::high_resolution_clock::now(); - std::chrono::duration time_taken = end_time - start_time; + clock_t end_time = std::clock(); + double time_taken = static_cast(end_time - start_time) / + static_cast(CLOCKS_PER_SEC); - std::cout - << std::endl - << N << "^th Fibonacci number: " << result << std::endl - << "Number of digits: " << result.num_digits() << std::endl - << "Time taken: " << time_taken.count() << " s" << std::endl; + std::cout << std::endl + << N << "^th Fibonacci number: " << result << std::endl + << "Number of digits: " << result.num_digits() << std::endl + << "Time taken: " << std::scientific << time_taken << " s" + << std::endl; N = 5000; - if (fib(N) == large_number("3878968454388325633701916308325905312082127714646245106160597214895550139044037097010822916462210669479293452858882973813483102008954982940361430156911478938364216563944106910214505634133706558656238254656700712525929903854933813928836378347518908762970712033337052923107693008518093849801803847813996748881765554653788291644268912980384613778969021502293082475666346224923071883324803280375039130352903304505842701147635242270210934637699104006714174883298422891491273104054328753298044273676822977244987749874555691907703880637046832794811358973739993110106219308149018570815397854379195305617510761053075688783766033667355445258844886241619210553457493675897849027988234351023599844663934853256411952221859563060475364645470760330902420806382584929156452876291575759142343809142302917491088984155209854432486594079793571316841692868039545309545388698114665082066862897420639323438488465240988742395873801976993820317174208932265468879364002630797780058759129671389634214252579116872755600360311370547754724604639987588046985178408674382863125")) - std::cout << "Test for " << N << "^th Fibonacci number passed!" << std::endl; + if (fib(N) == + large_number( + "387896845438832563370191630832590531208212771464624510616059721489" + "555013904403709701082291646221066947929345285888297381348310200895" + "498294036143015691147893836421656394410691021450563413370655865623" + "825465670071252592990385493381392883637834751890876297071203333705" + "292310769300851809384980180384781399674888176555465378829164426891" + "298038461377896902150229308247566634622492307188332480328037503913" + "035290330450584270114763524227021093463769910400671417488329842289" + "149127310405432875329804427367682297724498774987455569190770388063" + "704683279481135897373999311010621930814901857081539785437919530561" + "751076105307568878376603366735544525884488624161921055345749367589" + "784902798823435102359984466393485325641195222185956306047536464547" + "076033090242080638258492915645287629157575914234380914230291749108" + "898415520985443248659407979357131684169286803954530954538869811466" + "508206686289742063932343848846524098874239587380197699382031717420" + "893226546887936400263079778005875912967138963421425257911687275560" + "0360311370547754724604639987588046985178408674382863125")) + std::cout << "Test for " << N << "^th Fibonacci number passed!" + << std::endl; else - std::cerr << "Test for " << N << "^th Fibonacci number failed!" << std::endl; + std::cerr << "Test for " << N << "^th Fibonacci number failed!" + << std::endl; return 0; } \ No newline at end of file diff --git a/others/large_factorial.cpp b/others/large_factorial.cpp index 5ee116b4c..f06f4e7af 100644 --- a/others/large_factorial.cpp +++ b/others/large_factorial.cpp @@ -1,102 +1,97 @@ -#include #include -#include + +#include +#include + #include "large_number.h" -using namespace std; - -bool test1() -{ - cout << "---- Check 1\t"; +bool test1() { + std::cout << "---- Check 1\t"; unsigned int i, number = 10; large_number result; - for (i = 2; i <= number; i++) - /* Multiply every number from 2 thru N */ + for (i = 2; i <= number; i++) /* Multiply every number from 2 thru N */ result *= i; const char *known_reslt = "3628800"; /* check 1 */ - if (strlen(known_reslt) != result.num_digits()) - { - cerr << "Result lengths dont match! " << strlen(known_reslt) << " != " << result.num_digits() << endl; + if (strlen(known_reslt) != result.num_digits()) { + std::cerr << "Result lengths dont match! " << strlen(known_reslt) + << " != " << result.num_digits() << std::endl; return false; } const size_t N = result.num_digits(); - for (i = 0; i < N; i++) - { - if (known_reslt[i] != result.digit_char(i)) - { - cerr << i << "^th digit mismatch! " << known_reslt[i] << " != " << result.digit_char(i) << endl; + for (i = 0; i < N; i++) { + if (known_reslt[i] != result.digit_char(i)) { + std::cerr << i << "^th digit mismatch! " << known_reslt[i] + << " != " << result.digit_char(i) << std::endl; return false; } } - cout << "Passed!" << endl; + std::cout << "Passed!" << std::endl; return true; } -bool test2() -{ - cout << "---- Check 2\t"; +bool test2() { + std::cout << "---- Check 2\t"; unsigned int i, number = 100; large_number result; - for (i = 2; i <= number; i++) - /* Multiply every number from 2 thru N */ + for (i = 2; i <= number; i++) /* Multiply every number from 2 thru N */ result *= i; - const char *known_reslt = "93326215443944152681699238856266700490715968264381621468592963895217599993229915608941463976156518286253697920827223758251185210916864000000000000000000000000"; + const char *known_reslt = + "9332621544394415268169923885626670049071596826438162146859296389521759" + "9993229915608941463976156518286253697920827223758251185210916864000000" + "000000000000000000"; /* check 1 */ - if (strlen(known_reslt) != result.num_digits()) - { - cerr << "Result lengths dont match! " << strlen(known_reslt) << " != " << result.num_digits() << endl; + if (strlen(known_reslt) != result.num_digits()) { + std::cerr << "Result lengths dont match! " << strlen(known_reslt) + << " != " << result.num_digits() << std::endl; return false; } const size_t N = result.num_digits(); - for (i = 0; i < N; i++) - { - if (known_reslt[i] != result.digit_char(i)) - { - cerr << i << "^th digit mismatch! " << known_reslt[i] << " != " << result.digit_char(i) << endl; + for (i = 0; i < N; i++) { + if (known_reslt[i] != result.digit_char(i)) { + std::cerr << i << "^th digit mismatch! " << known_reslt[i] + << " != " << result.digit_char(i) << std::endl; return false; } } - cout << "Passed!" << endl; + std::cout << "Passed!" << std::endl; return true; } /** * Main program **/ -int main(int argc, char *argv[]) -{ +int main(int argc, char *argv[]) { int number, i; if (argc == 2) number = atoi(argv[1]); - else - { - printf("Enter the value of n(n starts from 0 ): "); - scanf("%d", &number); + else { + std::cout << "Enter the value of n(n starts from 0 ): "; + std::cin >> number; } large_number result; - auto start_time = chrono::high_resolution_clock::now(); - for (i = 2; i <= number; i++) - /* Multiply every number from 2 thru N */ + std::clock_t start_time = std::clock(); + for (i = 2; i <= number; i++) /* Multiply every number from 2 thru N */ result *= i; - auto end_time = chrono::high_resolution_clock::now(); - chrono::duration time_taken = end_time - start_time; + std::clock_t end_time = std::clock(); + double time_taken = + static_cast(end_time - start_time) / CLOCKS_PER_SEC; - cout << number << "! = " << result << endl - << "Number of digits: " << result.num_digits() << endl - << "Time taken: " << time_taken.count() << " s" - << endl; + std::cout << number << "! = " << result << std::endl + << "Number of digits: " << result.num_digits() << std::endl + << "Time taken: " << std::scientific << time_taken << " s" + << std::endl; test1(); test2(); diff --git a/others/large_number.h b/others/large_number.h index 8c7f688d0..4657e87af 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -5,10 +5,10 @@ #ifndef __LARGE_NUMBER__ #define __LARGE_NUMBER__ -#include -#include #include #include +#include +#include #include /** @@ -17,9 +17,8 @@ * digit to the number, perform multiplication of * large number with long unsigned integers. **/ -class large_number -{ -public: +class large_number { + public: large_number() /**< initializer with value = 1 */ { _digits.push_back(1); @@ -28,85 +27,79 @@ public: large_number(unsigned long n) /**< initializer from an integer */ { unsigned long carry = n; - do - { + do { add_digit(carry % 10); carry /= 10; } while (carry != 0); } - large_number(const large_number &a) /**< initializer from another large_number */ + large_number( + const large_number &a) /**< initializer from another large_number */ { _digits = a._digits; } - large_number(const std::vector &vec) /**< initializer from a vector */ + large_number( + const std::vector &vec) /**< initializer from a vector */ { _digits = vec; } large_number(const char *number_str) /**< initializer from a string */ { - for (size_t i = strlen(number_str); i > 0; i--) - { + for (size_t i = strlen(number_str); i > 0; i--) { unsigned char a = number_str[i - 1] - '0'; - if (a >= 0 && a <= 9) - _digits.push_back(a); + if (a >= 0 && a <= 9) _digits.push_back(a); } } /** * Function to check implementation **/ - static bool test() - { - std::cout << "------ Checking `large_number` class implementations\t" << std::endl; + static bool test() { + std::cout << "------ Checking `large_number` class implementations\t" + << std::endl; large_number a(40); // 1. test multiplication a *= 10; - if (a != large_number(400)) - { + if (a != large_number(400)) { std::cerr << "\tFailed 1/6 (" << a << "!=400)" << std::endl; return false; } std::cout << "\tPassed 1/6..."; // 2. test compound addition with integer a += 120; - if (a != large_number(520)) - { + if (a != large_number(520)) { std::cerr << "\tFailed 2/6 (" << a << "!=520)" << std::endl; return false; } std::cout << "\tPassed 2/6..."; // 3. test compound multiplication again a *= 10; - if (a != large_number(5200)) - { + if (a != large_number(5200)) { std::cerr << "\tFailed 3/6 (" << a << "!=5200)" << std::endl; return false; } std::cout << "\tPassed 3/6..."; // 4. test increment (prefix) ++a; - if (a != large_number(5201)) - { + if (a != large_number(5201)) { std::cerr << "\tFailed 4/6 (" << a << "!=5201)" << std::endl; return false; } std::cout << "\tPassed 4/6..."; // 5. test increment (postfix) a++; - if (a != large_number(5202)) - { + if (a != large_number(5202)) { std::cerr << "\tFailed 5/6 (" << a << "!=5202)" << std::endl; return false; } std::cout << "\tPassed 5/6..."; // 6. test addition with another large number a = a + large_number("7000000000000000000000000000000"); - if (a != large_number("7000000000000000000000000005202")) - { - std::cerr << "\tFailed 6/6 (" << a << "!=7000000000000000000000000005202)" << std::endl; + if (a != large_number("7000000000000000000000000005202")) { + std::cerr << "\tFailed 6/6 (" << a + << "!=7000000000000000000000000005202)" << std::endl; return false; } std::cout << "\tPassed 6/6..." << std::endl; @@ -116,10 +109,8 @@ public: /** * add a digit at MSB to the large number **/ - void add_digit(unsigned int value) - { - if (value > 9) - { + void add_digit(unsigned int value) { + if (value > 9) { std::cerr << "digit > 9!!\n"; exit(EXIT_FAILURE); } @@ -130,31 +121,23 @@ public: /** * Get number of digits in the number **/ - const size_t num_digits() const - { - return _digits.size(); - } + const size_t num_digits() const { return _digits.size(); } /** * operator over load to access the * i^th digit conveniently and also * assign value to it **/ - inline unsigned char &operator[](size_t n) - { - return this->_digits[n]; - } + inline unsigned char &operator[](size_t n) { return this->_digits[n]; } - inline const unsigned char &operator[](size_t n) const - { + inline const unsigned char &operator[](size_t n) const { return this->_digits[n]; } /** * operator overload to compare two numbers **/ - friend std::ostream &operator<<(std::ostream &out, const large_number &a) - { + friend std::ostream &operator<<(std::ostream &out, const large_number &a) { for (size_t i = a.num_digits(); i > 0; i--) out << static_cast(a[i - 1]); return out; @@ -163,30 +146,25 @@ public: /** * operator overload to compare two numbers **/ - friend bool operator==(const large_number &a, const large_number &b) - { + friend bool operator==(large_number const &a, large_number const &b) { size_t N = a.num_digits(); - if (N != b.num_digits()) - return false; + if (N != b.num_digits()) return false; for (size_t i = 0; i < N; i++) - if (a[i] != b[i]) - return false; + if (a[i] != b[i]) return false; return true; } /** * operator overload to compare two numbers **/ - friend bool operator!=(const large_number &a, const large_number &b) - { + friend bool operator!=(large_number const &a, large_number const &b) { return !(a == b); } /** * operator overload to increment (prefix) **/ - large_number &operator++() - { + large_number &operator++() { (*this) += 1; return *this; } @@ -194,8 +172,7 @@ public: /** * operator overload to increment (postfix) **/ - large_number operator++(int) - { + large_number operator++(int) { large_number tmp(_digits); ++(*this); return tmp; @@ -205,31 +182,28 @@ public: * operator overload to add **/ template - large_number &operator+=(T n) - { - if (typeid(T) == typeid(large_number)) // if adding with another large_number + large_number &operator+=(T n) { + if (typeid(T) == + typeid(large_number)) // if adding with another large_number { large_number *b = (large_number *)&n; const size_t max_L = std::max(this->num_digits(), b->num_digits()); unsigned int carry = 0; size_t i; - for (i = 0; i < max_L || carry != 0; i++) - { - if (i < b->num_digits()) - carry += (*b)[i]; - if (i < this->num_digits()) - carry += (*this)[i]; + for (i = 0; i < max_L || carry != 0; i++) { + if (i < b->num_digits()) carry += (*b)[i]; + if (i < this->num_digits()) carry += (*this)[i]; if (i < this->num_digits()) (*this)[i] = carry % 10; else this->add_digit(carry % 10); carry /= 10; } - } - else if (std::is_integral::value) + } else if (std::is_integral::value) return (*this) += large_number(n); else - std::cerr << "Must be integer addition unsigned integer types." << std::endl; + std::cerr << "Must be integer addition unsigned integer types." + << std::endl; return *this; } @@ -237,8 +211,7 @@ public: * operator overload to perform addition **/ template - friend large_number &operator+(large_number &a, const T &b) - { + friend large_number &operator+(large_number &a, const T &b) { a += b; return a; } @@ -246,18 +219,15 @@ public: /** * assignment operator **/ - void operator=(const large_number &b) - { - _digits = b._digits; - } + void operator=(const large_number &b) { _digits = b._digits; } /** * operator overload to increment **/ template - large_number &operator*=(const T n) - { - static_assert(std::is_integral::value, "Must be integer addition unsigned integer types."); + large_number &operator*=(const T n) { + static_assert(std::is_integral::value, + "Must be integer addition unsigned integer types."); this->multiply(n); return *this; } @@ -265,46 +235,44 @@ public: /** * returns i^th digit as an ASCII character **/ - const char digit_char(size_t i) const - { + const char digit_char(size_t i) const { return _digits[num_digits() - i - 1] + '0'; } -private: + private: /** * multiply large number with another integer and * store the result in the same large number **/ template - void multiply(const T n) - { - static_assert(std::is_integral::value, "Can only have integer types."); - // assert(!(std::is_signed::value)); //, "Implemented only for unsigned integer types."); + void multiply(const T n) { + static_assert(std::is_integral::value, + "Can only have integer types."); + // assert(!(std::is_signed::value)); //, "Implemented only for + // unsigned integer types."); size_t i; unsigned long long carry = 0, temp; - for (i = 0; i < this->num_digits(); i++) - { + for (i = 0; i < this->num_digits(); i++) { temp = (*this)[i] * n; temp += carry; if (temp < 10) carry = 0; - else - { + else { carry = temp / 10; temp = temp % 10; } (*this)[i] = temp; } - while (carry != 0) - { + while (carry != 0) { this->add_digit(carry % 10); carry /= 10; } }; - std::vector _digits; /**< where individual digits are stored */ + std::vector + _digits; /**< where individual digits are stored */ }; #endif From e989ad0fe5bf7b59dadbb11bbc44aba7e6654756 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sun, 24 May 2020 16:02:00 -0400 Subject: [PATCH 13/24] cpp lint fixes --- others/fibonacci_large.cpp | 13 +++++++------ others/large_factorial.cpp | 6 +++--- 2 files changed, 10 insertions(+), 9 deletions(-) diff --git a/others/fibonacci_large.cpp b/others/fibonacci_large.cpp index bdfb201a5..0333feb81 100644 --- a/others/fibonacci_large.cpp +++ b/others/fibonacci_large.cpp @@ -7,12 +7,13 @@ * number that contains 10450 digits! **/ +#include #include #include -#include "large_number.h" +#include "./large_number.h" -large_number fib(unsigned long long n) { +large_number fib(uint64_t n) { large_number f0(1); large_number f1(1); @@ -26,10 +27,10 @@ large_number fib(unsigned long long n) { } int main(int argc, char *argv[]) { - unsigned long long N; - if (argc == 2) + uint64_t N; + if (argc == 2) { N = strtoull(argv[1], NULL, 10); - else { + } else { std::cout << "Enter N: "; std::cin >> N; } @@ -72,4 +73,4 @@ int main(int argc, char *argv[]) { << std::endl; return 0; -} \ No newline at end of file +} diff --git a/others/large_factorial.cpp b/others/large_factorial.cpp index f06f4e7af..6d5385589 100644 --- a/others/large_factorial.cpp +++ b/others/large_factorial.cpp @@ -3,7 +3,7 @@ #include #include -#include "large_number.h" +#include "./large_number.h" bool test1() { std::cout << "---- Check 1\t"; @@ -72,9 +72,9 @@ bool test2() { int main(int argc, char *argv[]) { int number, i; - if (argc == 2) + if (argc == 2) { number = atoi(argv[1]); - else { + } else { std::cout << "Enter the value of n(n starts from 0 ): "; std::cin >> number; } From 045a1dc977f309a52d121b1efe66fb6a25e3fb29 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sun, 24 May 2020 16:08:00 -0400 Subject: [PATCH 14/24] more cpp lint fixes --- others/large_number.h | 30 ++++++++++++++++-------------- 1 file changed, 16 insertions(+), 14 deletions(-) diff --git a/others/large_number.h b/others/large_number.h index 4657e87af..abc63b765 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -3,8 +3,8 @@ * @email krishna (dot) vedala (at) ieee (dot) org **/ -#ifndef __LARGE_NUMBER__ -#define __LARGE_NUMBER__ +#ifndef OTHERS_LARGE_NUMBER_H_ +#define OTHERS_LARGE_NUMBER_H_ #include #include #include @@ -18,11 +18,8 @@ * large number with long unsigned integers. **/ class large_number { - public: - large_number() /**< initializer with value = 1 */ - { - _digits.push_back(1); - } +public: + large_number() /**< initializer with value = 1 */ { _digits.push_back(1); } large_number(unsigned long n) /**< initializer from an integer */ { @@ -49,7 +46,8 @@ class large_number { { for (size_t i = strlen(number_str); i > 0; i--) { unsigned char a = number_str[i - 1] - '0'; - if (a >= 0 && a <= 9) _digits.push_back(a); + if (a >= 0 && a <= 9) + _digits.push_back(a); } } @@ -148,9 +146,11 @@ class large_number { **/ friend bool operator==(large_number const &a, large_number const &b) { size_t N = a.num_digits(); - if (N != b.num_digits()) return false; + if (N != b.num_digits()) + return false; for (size_t i = 0; i < N; i++) - if (a[i] != b[i]) return false; + if (a[i] != b[i]) + return false; return true; } @@ -191,8 +191,10 @@ class large_number { unsigned int carry = 0; size_t i; for (i = 0; i < max_L || carry != 0; i++) { - if (i < b->num_digits()) carry += (*b)[i]; - if (i < this->num_digits()) carry += (*this)[i]; + if (i < b->num_digits()) + carry += (*b)[i]; + if (i < this->num_digits()) + carry += (*this)[i]; if (i < this->num_digits()) (*this)[i] = carry % 10; else @@ -239,7 +241,7 @@ class large_number { return _digits[num_digits() - i - 1] + '0'; } - private: +private: /** * multiply large number with another integer and * store the result in the same large number @@ -275,4 +277,4 @@ class large_number { _digits; /**< where individual digits are stored */ }; -#endif +#endif // OTHERS_LARGE_NUMBER_H_ From ca08e3e9a21a16ad08d97f3ceb06d4a511bc1c39 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sun, 24 May 2020 16:08:12 -0400 Subject: [PATCH 15/24] updated vscode settings --- .vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 0ab2708d0..5815b2666 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -64,7 +64,7 @@ "valarray": "cpp", "algorithm": "cpp" }, - "C_Cpp.clang_format_style": "{BasedOnStyle: Google, IndentWidth: 4, ColumnLimit: 80, UseTab: Never}", + "C_Cpp.clang_format_style": "{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4,, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -4, NamespaceIndentation: All }", "editor.formatOnSave": true, "editor.formatOnType": true, "editor.formatOnPaste": true From 6276e4ec06b1d698cc3e0ca5e5d9dd9b57097b32 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sun, 24 May 2020 16:11:08 -0400 Subject: [PATCH 16/24] use cinttypes for size specific int type --- others/large_number.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/others/large_number.h b/others/large_number.h index abc63b765..84d885f67 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -6,6 +6,7 @@ #ifndef OTHERS_LARGE_NUMBER_H_ #define OTHERS_LARGE_NUMBER_H_ #include +#include #include #include #include @@ -21,9 +22,9 @@ class large_number { public: large_number() /**< initializer with value = 1 */ { _digits.push_back(1); } - large_number(unsigned long n) /**< initializer from an integer */ + large_number(uint64_t n) /**< initializer from an integer */ { - unsigned long carry = n; + uint64_t carry = n; do { add_digit(carry % 10); carry /= 10; From b802dbe077faf117cce2203d1a5c33064a12c9e5 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sun, 24 May 2020 16:24:41 -0400 Subject: [PATCH 17/24] code cleanup --- others/large_number.h | 471 +++++++++++++++++++++--------------------- 1 file changed, 231 insertions(+), 240 deletions(-) diff --git a/others/large_number.h b/others/large_number.h index 84d885f67..4f3851053 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -5,6 +5,7 @@ #ifndef OTHERS_LARGE_NUMBER_H_ #define OTHERS_LARGE_NUMBER_H_ +#include #include #include #include @@ -19,263 +20,253 @@ * large number with long unsigned integers. **/ class large_number { -public: - large_number() /**< initializer with value = 1 */ { _digits.push_back(1); } + public: + /**< initializer with value = 1 */ + large_number() { _digits.push_back(1); } - large_number(uint64_t n) /**< initializer from an integer */ - { - uint64_t carry = n; - do { - add_digit(carry % 10); - carry /= 10; - } while (carry != 0); + /**< initializer from an integer */ + explicit large_number(uint64_t n) { + uint64_t carry = n; + do { + add_digit(carry % 10); + carry /= 10; + } while (carry != 0); + } + + /**< initializer from another large_number */ + explicit large_number(const large_number &a) { _digits = a._digits; } + + /**< initializer from a vector */ + explicit large_number(const std::vector &vec) { + _digits = vec; + } + + /**< initializer from a string */ + explicit large_number(const char *number_str) { + for (size_t i = strlen(number_str); i > 0; i--) { + unsigned char a = number_str[i - 1] - '0'; + if (a >= 0 && a <= 9) _digits.push_back(a); + } + } + + /** + * Function to check implementation + **/ + static bool test() { + std::cout << "------ Checking `large_number` class implementations\t" + << std::endl; + large_number a(40); + // 1. test multiplication + a *= 10; + if (a != large_number(400)) { + std::cerr << "\tFailed 1/6 (" << a << "!=400)" << std::endl; + return false; + } + std::cout << "\tPassed 1/6..."; + // 2. test compound addition with integer + a += 120; + if (a != large_number(520)) { + std::cerr << "\tFailed 2/6 (" << a << "!=520)" << std::endl; + return false; + } + std::cout << "\tPassed 2/6..."; + // 3. test compound multiplication again + a *= 10; + if (a != large_number(5200)) { + std::cerr << "\tFailed 3/6 (" << a << "!=5200)" << std::endl; + return false; + } + std::cout << "\tPassed 3/6..."; + // 4. test increment (prefix) + ++a; + if (a != large_number(5201)) { + std::cerr << "\tFailed 4/6 (" << a << "!=5201)" << std::endl; + return false; + } + std::cout << "\tPassed 4/6..."; + // 5. test increment (postfix) + a++; + if (a != large_number(5202)) { + std::cerr << "\tFailed 5/6 (" << a << "!=5202)" << std::endl; + return false; + } + std::cout << "\tPassed 5/6..."; + // 6. test addition with another large number + a = a + large_number("7000000000000000000000000000000"); + if (a != large_number("7000000000000000000000000005202")) { + std::cerr << "\tFailed 6/6 (" << a << "!=7000000000000000000000000005202)" + << std::endl; + return false; + } + std::cout << "\tPassed 6/6..." << std::endl; + return true; + } + + /** + * add a digit at MSB to the large number + **/ + void add_digit(unsigned int value) { + if (value > 9) { + std::cerr << "digit > 9!!\n"; + exit(EXIT_FAILURE); } - large_number( - const large_number &a) /**< initializer from another large_number */ - { - _digits = a._digits; - } + _digits.push_back(value); + } - large_number( - const std::vector &vec) /**< initializer from a vector */ - { - _digits = vec; - } + /** + * Get number of digits in the number + **/ + const size_t num_digits() const { return _digits.size(); } - large_number(const char *number_str) /**< initializer from a string */ - { - for (size_t i = strlen(number_str); i > 0; i--) { - unsigned char a = number_str[i - 1] - '0'; - if (a >= 0 && a <= 9) - _digits.push_back(a); - } - } + /** + * operator over load to access the + * i^th digit conveniently and also + * assign value to it + **/ + inline unsigned char &operator[](size_t n) { return this->_digits[n]; } - /** - * Function to check implementation - **/ - static bool test() { - std::cout << "------ Checking `large_number` class implementations\t" - << std::endl; - large_number a(40); - // 1. test multiplication - a *= 10; - if (a != large_number(400)) { - std::cerr << "\tFailed 1/6 (" << a << "!=400)" << std::endl; - return false; - } - std::cout << "\tPassed 1/6..."; - // 2. test compound addition with integer - a += 120; - if (a != large_number(520)) { - std::cerr << "\tFailed 2/6 (" << a << "!=520)" << std::endl; - return false; - } - std::cout << "\tPassed 2/6..."; - // 3. test compound multiplication again - a *= 10; - if (a != large_number(5200)) { - std::cerr << "\tFailed 3/6 (" << a << "!=5200)" << std::endl; - return false; - } - std::cout << "\tPassed 3/6..."; - // 4. test increment (prefix) - ++a; - if (a != large_number(5201)) { - std::cerr << "\tFailed 4/6 (" << a << "!=5201)" << std::endl; - return false; - } - std::cout << "\tPassed 4/6..."; - // 5. test increment (postfix) - a++; - if (a != large_number(5202)) { - std::cerr << "\tFailed 5/6 (" << a << "!=5202)" << std::endl; - return false; - } - std::cout << "\tPassed 5/6..."; - // 6. test addition with another large number - a = a + large_number("7000000000000000000000000000000"); - if (a != large_number("7000000000000000000000000005202")) { - std::cerr << "\tFailed 6/6 (" << a - << "!=7000000000000000000000000005202)" << std::endl; - return false; - } - std::cout << "\tPassed 6/6..." << std::endl; - return true; - } + inline const unsigned char &operator[](size_t n) const { + return this->_digits[n]; + } - /** - * add a digit at MSB to the large number - **/ - void add_digit(unsigned int value) { - if (value > 9) { - std::cerr << "digit > 9!!\n"; - exit(EXIT_FAILURE); - } + /** + * operator overload to compare two numbers + **/ + friend std::ostream &operator<<(std::ostream &out, const large_number &a) { + for (size_t i = a.num_digits(); i > 0; i--) + out << static_cast(a[i - 1]); + return out; + } - _digits.push_back(value); - } + /** + * operator overload to compare two numbers + **/ + friend bool operator==(large_number const &a, large_number const &b) { + size_t N = a.num_digits(); + if (N != b.num_digits()) return false; + for (size_t i = 0; i < N; i++) + if (a[i] != b[i]) return false; + return true; + } - /** - * Get number of digits in the number - **/ - const size_t num_digits() const { return _digits.size(); } + /** + * operator overload to compare two numbers + **/ + friend bool operator!=(large_number const &a, large_number const &b) { + return !(a == b); + } - /** - * operator over load to access the - * i^th digit conveniently and also - * assign value to it - **/ - inline unsigned char &operator[](size_t n) { return this->_digits[n]; } + /** + * operator overload to increment (prefix) + **/ + large_number &operator++() { + (*this) += 1; + return *this; + } - inline const unsigned char &operator[](size_t n) const { - return this->_digits[n]; - } + /** + * operator overload to increment (postfix) + **/ + large_number operator++(int) { + large_number tmp(_digits); + ++(*this); + return tmp; + } - /** - * operator overload to compare two numbers - **/ - friend std::ostream &operator<<(std::ostream &out, const large_number &a) { - for (size_t i = a.num_digits(); i > 0; i--) - out << static_cast(a[i - 1]); - return out; - } - - /** - * operator overload to compare two numbers - **/ - friend bool operator==(large_number const &a, large_number const &b) { - size_t N = a.num_digits(); - if (N != b.num_digits()) - return false; - for (size_t i = 0; i < N; i++) - if (a[i] != b[i]) - return false; - return true; - } - - /** - * operator overload to compare two numbers - **/ - friend bool operator!=(large_number const &a, large_number const &b) { - return !(a == b); - } - - /** - * operator overload to increment (prefix) - **/ - large_number &operator++() { - (*this) += 1; - return *this; - } - - /** - * operator overload to increment (postfix) - **/ - large_number operator++(int) { - large_number tmp(_digits); - ++(*this); - return tmp; - } - - /** - * operator overload to add - **/ - template - large_number &operator+=(T n) { - if (typeid(T) == - typeid(large_number)) // if adding with another large_number - { - large_number *b = (large_number *)&n; - const size_t max_L = std::max(this->num_digits(), b->num_digits()); - unsigned int carry = 0; - size_t i; - for (i = 0; i < max_L || carry != 0; i++) { - if (i < b->num_digits()) - carry += (*b)[i]; - if (i < this->num_digits()) - carry += (*this)[i]; - if (i < this->num_digits()) - (*this)[i] = carry % 10; - else - this->add_digit(carry % 10); - carry /= 10; - } - } else if (std::is_integral::value) - return (*this) += large_number(n); + /** + * operator overload to add + **/ + template + large_number &operator+=(T n) { + // if adding with another large_number + if (typeid(T) == typeid(large_number)) { + large_number *b = static_cast(&n); + const size_t max_L = std::max(this->num_digits(), b->num_digits()); + unsigned int carry = 0; + size_t i; + for (i = 0; i < max_L || carry != 0; i++) { + if (i < b->num_digits()) carry += (*b)[i]; + if (i < this->num_digits()) carry += (*this)[i]; + if (i < this->num_digits()) + (*this)[i] = carry % 10; else - std::cerr << "Must be integer addition unsigned integer types." - << std::endl; - return *this; + this->add_digit(carry % 10); + carry /= 10; + } + } else if (std::is_integral::value) { + return (*this) += large_number(n); + } else { + std::cerr << "Must be integer addition unsigned integer types." + << std::endl; + } + return *this; + } + + /** + * operator overload to perform addition + **/ + template + friend large_number &operator+(const large_number &a, const T &b) { + a += b; + return a; + } + + /** + * assignment operator + **/ + void operator=(const large_number &b) { _digits = b._digits; } + + /** + * operator overload to increment + **/ + template + large_number &operator*=(const T n) { + static_assert(std::is_integral::value, + "Must be integer addition unsigned integer types."); + this->multiply(n); + return *this; + } + + /** + * returns i^th digit as an ASCII character + **/ + const char digit_char(size_t i) const { + return _digits[num_digits() - i - 1] + '0'; + } + + private: + /** + * multiply large number with another integer and + * store the result in the same large number + **/ + template + void multiply(const T n) { + static_assert(std::is_integral::value, "Can only have integer types."); + // assert(!(std::is_signed::value)); //, "Implemented only for + // unsigned integer types."); + + size_t i; + uint64_t carry = 0, temp; + for (i = 0; i < this->num_digits(); i++) { + temp = (*this)[i] * n; + temp += carry; + if (temp < 10) { + carry = 0; + } else { + carry = temp / 10; + temp = temp % 10; + } + (*this)[i] = temp; } - /** - * operator overload to perform addition - **/ - template - friend large_number &operator+(large_number &a, const T &b) { - a += b; - return a; + while (carry != 0) { + this->add_digit(carry % 10); + carry /= 10; } + } - /** - * assignment operator - **/ - void operator=(const large_number &b) { _digits = b._digits; } - - /** - * operator overload to increment - **/ - template - large_number &operator*=(const T n) { - static_assert(std::is_integral::value, - "Must be integer addition unsigned integer types."); - this->multiply(n); - return *this; - } - - /** - * returns i^th digit as an ASCII character - **/ - const char digit_char(size_t i) const { - return _digits[num_digits() - i - 1] + '0'; - } - -private: - /** - * multiply large number with another integer and - * store the result in the same large number - **/ - template - void multiply(const T n) { - static_assert(std::is_integral::value, - "Can only have integer types."); - // assert(!(std::is_signed::value)); //, "Implemented only for - // unsigned integer types."); - - size_t i; - unsigned long long carry = 0, temp; - for (i = 0; i < this->num_digits(); i++) { - temp = (*this)[i] * n; - temp += carry; - if (temp < 10) - carry = 0; - else { - carry = temp / 10; - temp = temp % 10; - } - (*this)[i] = temp; - } - - while (carry != 0) { - this->add_digit(carry % 10); - carry /= 10; - } - }; - - std::vector - _digits; /**< where individual digits are stored */ + std::vector _digits; /**< where individual digits are stored */ }; #endif // OTHERS_LARGE_NUMBER_H_ From 58f77c404696402bc5b45174ad1f02baaedfda4b Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Sun, 24 May 2020 16:27:18 -0400 Subject: [PATCH 18/24] remove erroneous const from `+` operator --- others/large_number.h | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/others/large_number.h b/others/large_number.h index 4f3851053..38d9125de 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -207,7 +207,7 @@ class large_number { * operator overload to perform addition **/ template - friend large_number &operator+(const large_number &a, const T &b) { + friend large_number &operator+(large_number &a, const T &b) { a += b; return a; } From 251c32d8b334779c0ac891422a2722d3ba4660fa Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Mon, 25 May 2020 11:03:30 -0400 Subject: [PATCH 19/24] Update .vscode/settings.json removed additional comma in the JSON Co-authored-by: Christian Clauss --- .vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 5815b2666..4d291141b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -64,7 +64,7 @@ "valarray": "cpp", "algorithm": "cpp" }, - "C_Cpp.clang_format_style": "{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4,, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -4, NamespaceIndentation: All }", + "C_Cpp.clang_format_style": "{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -4, NamespaceIndentation: All }", "editor.formatOnSave": true, "editor.formatOnType": true, "editor.formatOnPaste": true From c892cbadc630bac45ea9ffbb2bada8a427187bba Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Tue, 26 May 2020 18:07:41 -0400 Subject: [PATCH 20/24] fixed code for lint and copy constructor --- others/fibonacci_large.cpp | 7 +- others/large_number.h | 470 +++++++++++++++++++------------------ 2 files changed, 244 insertions(+), 233 deletions(-) diff --git a/others/fibonacci_large.cpp b/others/fibonacci_large.cpp index 0333feb81..6f36702a2 100644 --- a/others/fibonacci_large.cpp +++ b/others/fibonacci_large.cpp @@ -18,11 +18,12 @@ large_number fib(uint64_t n) { large_number f1(1); do { - large_number f2 = f0 + f1; - f0 = f1; - f1 = f2; + large_number f2 = f1; + f1 += f0; + f0 = f2; n--; } while (n > 2); // since we start from 2 + return f1; } diff --git a/others/large_number.h b/others/large_number.h index 38d9125de..8ea8190b6 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -1,4 +1,5 @@ /** + * @file * @author Krishna Vedala * @email krishna (dot) vedala (at) ieee (dot) org **/ @@ -21,252 +22,261 @@ **/ class large_number { public: - /**< initializer with value = 1 */ - large_number() { _digits.push_back(1); } + /**< initializer with value = 1 */ + large_number() { _digits.push_back(1); } - /**< initializer from an integer */ - explicit large_number(uint64_t n) { - uint64_t carry = n; - do { - add_digit(carry % 10); - carry /= 10; - } while (carry != 0); - } + // /**< initializer from an integer */ + // explicit large_number(uint64_t n) { + // uint64_t carry = n; + // do { + // add_digit(carry % 10); + // carry /= 10; + // } while (carry != 0); + // } - /**< initializer from another large_number */ - explicit large_number(const large_number &a) { _digits = a._digits; } - - /**< initializer from a vector */ - explicit large_number(const std::vector &vec) { - _digits = vec; - } - - /**< initializer from a string */ - explicit large_number(const char *number_str) { - for (size_t i = strlen(number_str); i > 0; i--) { - unsigned char a = number_str[i - 1] - '0'; - if (a >= 0 && a <= 9) _digits.push_back(a); - } - } - - /** - * Function to check implementation - **/ - static bool test() { - std::cout << "------ Checking `large_number` class implementations\t" - << std::endl; - large_number a(40); - // 1. test multiplication - a *= 10; - if (a != large_number(400)) { - std::cerr << "\tFailed 1/6 (" << a << "!=400)" << std::endl; - return false; - } - std::cout << "\tPassed 1/6..."; - // 2. test compound addition with integer - a += 120; - if (a != large_number(520)) { - std::cerr << "\tFailed 2/6 (" << a << "!=520)" << std::endl; - return false; - } - std::cout << "\tPassed 2/6..."; - // 3. test compound multiplication again - a *= 10; - if (a != large_number(5200)) { - std::cerr << "\tFailed 3/6 (" << a << "!=5200)" << std::endl; - return false; - } - std::cout << "\tPassed 3/6..."; - // 4. test increment (prefix) - ++a; - if (a != large_number(5201)) { - std::cerr << "\tFailed 4/6 (" << a << "!=5201)" << std::endl; - return false; - } - std::cout << "\tPassed 4/6..."; - // 5. test increment (postfix) - a++; - if (a != large_number(5202)) { - std::cerr << "\tFailed 5/6 (" << a << "!=5202)" << std::endl; - return false; - } - std::cout << "\tPassed 5/6..."; - // 6. test addition with another large number - a = a + large_number("7000000000000000000000000000000"); - if (a != large_number("7000000000000000000000000005202")) { - std::cerr << "\tFailed 6/6 (" << a << "!=7000000000000000000000000005202)" - << std::endl; - return false; - } - std::cout << "\tPassed 6/6..." << std::endl; - return true; - } - - /** - * add a digit at MSB to the large number - **/ - void add_digit(unsigned int value) { - if (value > 9) { - std::cerr << "digit > 9!!\n"; - exit(EXIT_FAILURE); + /**< initializer from an integer */ + explicit large_number(int n) { + int carry = n; + do { + add_digit(carry % 10); + carry /= 10; + } while (carry != 0); } - _digits.push_back(value); - } + /**< initializer from another large_number */ + large_number(const large_number &a) : _digits(a._digits) {} - /** - * Get number of digits in the number - **/ - const size_t num_digits() const { return _digits.size(); } + /**< initializer from a vector */ + explicit large_number(std::vector &vec) : _digits(vec) {} - /** - * operator over load to access the - * i^th digit conveniently and also - * assign value to it - **/ - inline unsigned char &operator[](size_t n) { return this->_digits[n]; } - - inline const unsigned char &operator[](size_t n) const { - return this->_digits[n]; - } - - /** - * operator overload to compare two numbers - **/ - friend std::ostream &operator<<(std::ostream &out, const large_number &a) { - for (size_t i = a.num_digits(); i > 0; i--) - out << static_cast(a[i - 1]); - return out; - } - - /** - * operator overload to compare two numbers - **/ - friend bool operator==(large_number const &a, large_number const &b) { - size_t N = a.num_digits(); - if (N != b.num_digits()) return false; - for (size_t i = 0; i < N; i++) - if (a[i] != b[i]) return false; - return true; - } - - /** - * operator overload to compare two numbers - **/ - friend bool operator!=(large_number const &a, large_number const &b) { - return !(a == b); - } - - /** - * operator overload to increment (prefix) - **/ - large_number &operator++() { - (*this) += 1; - return *this; - } - - /** - * operator overload to increment (postfix) - **/ - large_number operator++(int) { - large_number tmp(_digits); - ++(*this); - return tmp; - } - - /** - * operator overload to add - **/ - template - large_number &operator+=(T n) { - // if adding with another large_number - if (typeid(T) == typeid(large_number)) { - large_number *b = static_cast(&n); - const size_t max_L = std::max(this->num_digits(), b->num_digits()); - unsigned int carry = 0; - size_t i; - for (i = 0; i < max_L || carry != 0; i++) { - if (i < b->num_digits()) carry += (*b)[i]; - if (i < this->num_digits()) carry += (*this)[i]; - if (i < this->num_digits()) - (*this)[i] = carry % 10; - else - this->add_digit(carry % 10); - carry /= 10; - } - } else if (std::is_integral::value) { - return (*this) += large_number(n); - } else { - std::cerr << "Must be integer addition unsigned integer types." - << std::endl; + /**< initializer from a string */ + explicit large_number(char const *number_str) { + for (size_t i = strlen(number_str); i > 0; i--) { + unsigned char a = number_str[i - 1] - '0'; + if (a >= 0 && a <= 9) _digits.push_back(a); + } } - return *this; - } - /** - * operator overload to perform addition - **/ - template - friend large_number &operator+(large_number &a, const T &b) { - a += b; - return a; - } + /** + * Function to check implementation + **/ + static bool test() { + std::cout << "------ Checking `large_number` class implementations\t" + << std::endl; + large_number a(40); + // 1. test multiplication + a *= 10; + if (a != large_number(400)) { + std::cerr << "\tFailed 1/6 (" << a << "!=400)" << std::endl; + return false; + } + std::cout << "\tPassed 1/6..."; + // 2. test compound addition with integer + a += 120; + if (a != large_number(520)) { + std::cerr << "\tFailed 2/6 (" << a << "!=520)" << std::endl; + return false; + } + std::cout << "\tPassed 2/6..."; + // 3. test compound multiplication again + a *= 10; + if (a != large_number(5200)) { + std::cerr << "\tFailed 3/6 (" << a << "!=5200)" << std::endl; + return false; + } + std::cout << "\tPassed 3/6..."; + // 4. test increment (prefix) + ++a; + if (a != large_number(5201)) { + std::cerr << "\tFailed 4/6 (" << a << "!=5201)" << std::endl; + return false; + } + std::cout << "\tPassed 4/6..."; + // 5. test increment (postfix) + a++; + if (a != large_number(5202)) { + std::cerr << "\tFailed 5/6 (" << a << "!=5202)" << std::endl; + return false; + } + std::cout << "\tPassed 5/6..."; + // 6. test addition with another large number + a = a + large_number("7000000000000000000000000000000"); + if (a != large_number("7000000000000000000000000005202")) { + std::cerr << "\tFailed 6/6 (" << a + << "!=7000000000000000000000000005202)" << std::endl; + return false; + } + std::cout << "\tPassed 6/6..." << std::endl; + return true; + } - /** - * assignment operator - **/ - void operator=(const large_number &b) { _digits = b._digits; } + /** + * add a digit at MSB to the large number + **/ + void add_digit(unsigned int value) { + if (value > 9) { + std::cerr << "digit > 9!!\n"; + exit(EXIT_FAILURE); + } - /** - * operator overload to increment - **/ - template - large_number &operator*=(const T n) { - static_assert(std::is_integral::value, - "Must be integer addition unsigned integer types."); - this->multiply(n); - return *this; - } + _digits.push_back(value); + } - /** - * returns i^th digit as an ASCII character - **/ - const char digit_char(size_t i) const { - return _digits[num_digits() - i - 1] + '0'; - } + /** + * Get number of digits in the number + **/ + const size_t num_digits() const { return _digits.size(); } + + /** + * operator over load to access the + * i^th digit conveniently and also + * assign value to it + **/ + inline unsigned char &operator[](size_t n) { return this->_digits[n]; } + + inline const unsigned char &operator[](size_t n) const { + return this->_digits[n]; + } + + /** + * operator overload to compare two numbers + **/ + friend std::ostream &operator<<(std::ostream &out, const large_number &a) { + for (size_t i = a.num_digits(); i > 0; i--) + out << static_cast(a[i - 1]); + return out; + } + + /** + * operator overload to compare two numbers + **/ + friend bool operator==(large_number const &a, large_number const &b) { + size_t N = a.num_digits(); + if (N != b.num_digits()) return false; + for (size_t i = 0; i < N; i++) + if (a[i] != b[i]) return false; + return true; + } + + /** + * operator overload to compare two numbers + **/ + friend bool operator!=(large_number const &a, large_number const &b) { + return !(a == b); + } + + /** + * operator overload to increment (prefix) + **/ + large_number &operator++() { + (*this) += 1; + return *this; + } + + /** + * operator overload to increment (postfix) + **/ + large_number &operator++(int) { + large_number tmp(_digits); + ++(*this); + return tmp; + } + + /** + * operator overload to add + **/ + large_number &operator+=(large_number n) { + // if adding with another large_number + large_number *b = reinterpret_cast(&n); + const size_t max_L = std::max(this->num_digits(), b->num_digits()); + unsigned int carry = 0; + size_t i; + for (i = 0; i < max_L || carry != 0; i++) { + if (i < b->num_digits()) carry += (*b)[i]; + if (i < this->num_digits()) carry += (*this)[i]; + if (i < this->num_digits()) + (*this)[i] = carry % 10; + else + this->add_digit(carry % 10); + carry /= 10; + } + return *this; + } + + large_number &operator+=(int n) { return (*this) += large_number(n); } + // large_number &operator+=(uint64_t n) { return (*this) += large_number(n); + // } + + /** + * operator overload to perform addition + **/ + template + friend large_number &operator+(const large_number &a, const T &b) { + large_number c = a; + c += b; + return c; + } + + /** + * assignment operator + **/ + large_number &operator=(const large_number &b) { + this->_digits = b._digits; + return *this; + } + + /** + * operator overload to increment + **/ + template + large_number &operator*=(const T n) { + static_assert(std::is_integral::value, + "Must be integer addition unsigned integer types."); + this->multiply(n); + return *this; + } + + /** + * returns i^th digit as an ASCII character + **/ + const char digit_char(size_t i) const { + return _digits[num_digits() - i - 1] + '0'; + } private: - /** - * multiply large number with another integer and - * store the result in the same large number - **/ - template - void multiply(const T n) { - static_assert(std::is_integral::value, "Can only have integer types."); - // assert(!(std::is_signed::value)); //, "Implemented only for - // unsigned integer types."); + /** + * multiply large number with another integer and + * store the result in the same large number + **/ + template + void multiply(const T n) { + static_assert(std::is_integral::value, + "Can only have integer types."); + // assert(!(std::is_signed::value)); //, "Implemented only for + // unsigned integer types."); - size_t i; - uint64_t carry = 0, temp; - for (i = 0; i < this->num_digits(); i++) { - temp = (*this)[i] * n; - temp += carry; - if (temp < 10) { - carry = 0; - } else { - carry = temp / 10; - temp = temp % 10; - } - (*this)[i] = temp; + size_t i; + uint64_t carry = 0, temp; + for (i = 0; i < this->num_digits(); i++) { + temp = (*this)[i] * n; + temp += carry; + if (temp < 10) { + carry = 0; + } else { + carry = temp / 10; + temp = temp % 10; + } + (*this)[i] = temp; + } + + while (carry != 0) { + this->add_digit(carry % 10); + carry /= 10; + } } - while (carry != 0) { - this->add_digit(carry % 10); - carry /= 10; - } - } - - std::vector _digits; /**< where individual digits are stored */ + std::vector + _digits; /**< where individual digits are stored */ }; #endif // OTHERS_LARGE_NUMBER_H_ From 77641f9b69b1f0e4b8e9988561ced94e5c343718 Mon Sep 17 00:00:00 2001 From: Krishna Vedala <7001608+kvedala@users.noreply.github.com> Date: Tue, 26 May 2020 18:15:00 -0400 Subject: [PATCH 21/24] use static variable to return reference for --- others/large_number.h | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/others/large_number.h b/others/large_number.h index 8ea8190b6..544682987 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -177,7 +177,7 @@ class large_number { * operator overload to increment (postfix) **/ large_number &operator++(int) { - large_number tmp(_digits); + static large_number tmp(_digits); ++(*this); return tmp; } @@ -212,7 +212,7 @@ class large_number { **/ template friend large_number &operator+(const large_number &a, const T &b) { - large_number c = a; + static large_number c = a; c += b; return c; } From 1a37992c1e7e538c7ffbe02c8448ef1abbdc1ab4 Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Wed, 27 May 2020 08:08:31 -0400 Subject: [PATCH 22/24] set 1 space for `private` and `public` keywords in cpp-classes --- .vscode/settings.json | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/.vscode/settings.json b/.vscode/settings.json index 4d291141b..0a257500b 100644 --- a/.vscode/settings.json +++ b/.vscode/settings.json @@ -64,7 +64,7 @@ "valarray": "cpp", "algorithm": "cpp" }, - "C_Cpp.clang_format_style": "{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -4, NamespaceIndentation: All }", + "C_Cpp.clang_format_style": "{ BasedOnStyle: Google, UseTab: Never, IndentWidth: 4, TabWidth: 4, AllowShortIfStatementsOnASingleLine: false, IndentCaseLabels: true, ColumnLimit: 80, AccessModifierOffset: -3, NamespaceIndentation: All }", "editor.formatOnSave": true, "editor.formatOnType": true, "editor.formatOnPaste": true From 9965614174f64085422d1a82fa6a67273cc730fb Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Wed, 27 May 2020 17:32:10 -0400 Subject: [PATCH 23/24] added documetnation to large_factorial.cpp --- others/large_factorial.cpp | 20 ++++++++++++++++++-- 1 file changed, 18 insertions(+), 2 deletions(-) diff --git a/others/large_factorial.cpp b/others/large_factorial.cpp index 6d5385589..1027f41ab 100644 --- a/others/large_factorial.cpp +++ b/others/large_factorial.cpp @@ -1,10 +1,18 @@ -#include - +/** + * @file + * @brief Compute factorial of any arbitratily large number/ + * + * @see factorial.cpp + */ +#include #include #include #include "./large_number.h" +/** Test implementation for 10! Result must be 3628800. + * @returns True if test pass else False + */ bool test1() { std::cout << "---- Check 1\t"; unsigned int i, number = 10; @@ -34,6 +42,14 @@ bool test1() { return true; } +/** Test implementation for 100! The result is the 156 digit number: + * ``` + * 9332621544394415268169923885626670049071596826438162146859296389521759 + * 9993229915608941463976156518286253697920827223758251185210916864000000 + * 000000000000000000 + * ``` + * @returns True if test pass else False + */ bool test2() { std::cout << "---- Check 2\t"; unsigned int i, number = 100; From 772e7fb789be4a7db263bb2f1cabc0fc829f6042 Mon Sep 17 00:00:00 2001 From: Krishna Vedala Date: Wed, 27 May 2020 17:32:46 -0400 Subject: [PATCH 24/24] removed author details from comments for header file --- others/large_number.h | 21 +++++++++++++-------- 1 file changed, 13 insertions(+), 8 deletions(-) diff --git a/others/large_number.h b/others/large_number.h index 544682987..959622187 100644 --- a/others/large_number.h +++ b/others/large_number.h @@ -1,8 +1,8 @@ /** * @file - * @author Krishna Vedala - * @email krishna (dot) vedala (at) ieee (dot) org - **/ + * @brief Library to perform arithmatic operations on arbitrarily large + * numbers. + */ #ifndef OTHERS_LARGE_NUMBER_H_ #define OTHERS_LARGE_NUMBER_H_ @@ -53,7 +53,8 @@ class large_number { explicit large_number(char const *number_str) { for (size_t i = strlen(number_str); i > 0; i--) { unsigned char a = number_str[i - 1] - '0'; - if (a >= 0 && a <= 9) _digits.push_back(a); + if (a >= 0 && a <= 9) + _digits.push_back(a); } } @@ -152,9 +153,11 @@ class large_number { **/ friend bool operator==(large_number const &a, large_number const &b) { size_t N = a.num_digits(); - if (N != b.num_digits()) return false; + if (N != b.num_digits()) + return false; for (size_t i = 0; i < N; i++) - if (a[i] != b[i]) return false; + if (a[i] != b[i]) + return false; return true; } @@ -192,8 +195,10 @@ class large_number { unsigned int carry = 0; size_t i; for (i = 0; i < max_L || carry != 0; i++) { - if (i < b->num_digits()) carry += (*b)[i]; - if (i < this->num_digits()) carry += (*this)[i]; + if (i < b->num_digits()) + carry += (*b)[i]; + if (i < this->num_digits()) + carry += (*this)[i]; if (i < this->num_digits()) (*this)[i] = carry % 10; else