Advertisement
beefviper

BigNum

Oct 5th, 2021
855
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
C++ 4.88 KB | None | 0 0
  1. // BigNum.h
  2. #pragma once
  3.  
  4. #include <iostream>
  5. #include <string>
  6. #include <vector>
  7. #include <fstream>
  8. #include <sstream>
  9. #include <iterator>
  10. #include <bitset>
  11. #include <algorithm>
  12. #include <cstdint>
  13.  
  14. class BigNum
  15. {
  16. public:
  17.     BigNum() = default;
  18.     BigNum(uint64_t input_base, std::string input_number);
  19.     BigNum(uint64_t input_base, uint64_t input_number);
  20.  
  21.     uint64_t base = 0;
  22.     std::vector<uint64_t> number{};
  23.  
  24. protected:
  25.     friend std::ostream& operator<<(std::ostream& output, const BigNum& bignum);
  26.  
  27. private:
  28.  
  29. };
  30.  
  31. BigNum setup_number(std::string filename);
  32. BigNum add_numbers(BigNum& num1, BigNum& num2);
  33. std::string load_binary_number(std::string filename);
  34. BigNum multiply_numbers(BigNum& num1, BigNum& num2);
  35. BigNum to_decimal(BigNum& num);
  36.  
  37.  
  38. // BigNum.cpp
  39. BigNum::BigNum(uint64_t input_base, std::string input_number)
  40. {
  41.     if (input_base > 1)
  42.     {
  43.         base = input_base;
  44.         for (auto digit : input_number)
  45.         {
  46.             if (digit >= 48 && digit <= 57)
  47.             {
  48.                 number.push_back(digit - static_cast<uint64_t>('0'));
  49.             }
  50.             else if (digit >= 65 && digit <= 70)
  51.             {
  52.                 number.push_back(digit - static_cast<uint64_t>('A') + 10);
  53.             }
  54.             else if (digit >= 97 && digit <= 122)
  55.             {
  56.                 number.push_back(digit - static_cast<uint64_t>('a') + 10);
  57.             }
  58.             else
  59.             {
  60.                 std::cout << "error: BigNum constructor: invalid digit";
  61.                 exit(0);
  62.             }
  63.         }
  64.     }
  65. }
  66.  
  67.  
  68. BigNum::BigNum(uint64_t input_base, uint64_t input_number) :
  69.     BigNum(input_base, std::to_string(input_number))
  70. {
  71.  
  72. }
  73.  
  74. std::ostream& operator<<(std::ostream& output, const BigNum& bignum)
  75. {
  76.     int A = 10, Z = 35, a = 36, z = 61;
  77.  
  78.     for (auto digit : bignum.number)
  79.     {
  80.         if (digit >= A && digit <= Z)
  81.         {
  82.             output << (static_cast<char>(digit - 10 + 'A'));
  83.         }
  84.         else if (digit >= a && digit <= z)
  85.         {
  86.             output << (static_cast<char>(digit - 36 + 'a'));
  87.         }
  88.         else
  89.         {
  90.             output << digit;
  91.         }
  92.     }
  93.  
  94.     return output;
  95. }
  96.  
  97. BigNum setup_number(std::string filename)
  98. {
  99.     std::ifstream input_file;
  100.     input_file.open(filename, std::ios::binary);
  101.  
  102.     if (!input_file)
  103.     {
  104.         std::cout << "Failed to open file" << std::endl;
  105.         exit(0);
  106.     }
  107.  
  108.     std::stringstream binary_string;
  109.     std::istreambuf_iterator<char> in(input_file), in_end;
  110.     std::ostream_iterator<std::bitset<8>> out(binary_string, "");
  111.     std::copy(in, in_end, out);
  112.  
  113.     BigNum number{ 2 , binary_string.str() };
  114.  
  115.     return number;
  116. }
  117.  
  118. std::string load_binary_number(std::string filename)
  119. {
  120.     std::ifstream input_file;
  121.     input_file.open(filename, std::ios::binary);
  122.  
  123.     if (!input_file)
  124.     {
  125.         std::cout << "Failed to open file" << std::endl;
  126.         exit(0);
  127.     }
  128.  
  129.     std::stringstream binary_string;
  130.     std::istreambuf_iterator<char> in(input_file), in_end;
  131.     std::ostream_iterator<std::bitset<8>> out(binary_string, "");
  132.     std::copy(in, in_end, out);
  133.  
  134.     return binary_string.str();
  135. }
  136.  
  137. BigNum add_numbers(BigNum& num1, BigNum& num2)
  138. {
  139.     BigNum result{};
  140.  
  141.     if (num1.base == num2.base)
  142.     {
  143.         result.base = num1.base;
  144.     }
  145.     else
  146.     {
  147.         return result;
  148.     }
  149.  
  150.     auto it1 = num1.number.rbegin();
  151.     auto it2 = num2.number.rbegin();
  152.  
  153.     uint64_t carry = 0;
  154.  
  155.     while (it1 != num1.number.rend() || it2 != num2.number.rend())
  156.     {
  157.         uint64_t n1 = (it1 != num1.number.rend()) ? *it1++ : 0;
  158.         uint64_t n2 = (it2 != num2.number.rend()) ? *it2++ : 0;
  159.  
  160.         uint64_t temp = n1 + n2 + carry;
  161.         carry = 0;
  162.  
  163.         if (temp > num1.base - 1)
  164.         {
  165.             temp = temp % num1.base;
  166.             carry = 1;
  167.         }
  168.  
  169.         result.number.push_back(temp);
  170.     }
  171.  
  172.     if (carry == 1)
  173.     {
  174.         result.number.push_back(1);
  175.     }
  176.  
  177.     std::reverse(result.number.begin(), result.number.end());
  178.  
  179.     return result;
  180. }
  181.  
  182. BigNum multiply_numbers(BigNum& num1, BigNum& num2)
  183. {
  184.     BigNum result{};
  185.  
  186.     if (num1.base == num2.base)
  187.     {
  188.         result.base = num1.base;
  189.     }
  190.     else
  191.     {
  192.         return result;
  193.     }
  194.  
  195.     auto it1 = num1.number.rbegin();
  196.     uint64_t add_zeroes = 0;
  197.  
  198.     while (it1 != num1.number.rend())
  199.     {
  200.         auto it2 = num2.number.rbegin();
  201.        
  202.         BigNum number{};
  203.         number.base = num1.base;
  204.  
  205.         uint64_t base = num1.base;
  206.         uint64_t digit = 0;
  207.         uint64_t carry = 0;
  208.  
  209.         while (it2 != num2.number.rend())
  210.         {
  211.             auto tmp = *it1 * *it2 + carry;
  212.  
  213.             digit = tmp % base;
  214.             carry = tmp / base;
  215.  
  216.             number.number.push_back(digit);
  217.  
  218.             it2++;
  219.         }
  220.  
  221.         if (carry != 0)
  222.         {
  223.             number.number.push_back(carry);
  224.         }
  225.  
  226.         std::reverse(number.number.begin(), number.number.end());
  227.  
  228.         for (uint64_t i = 0; i < add_zeroes; i++)
  229.         {
  230.             number.number.push_back(0);
  231.         }
  232.  
  233.         add_zeroes++;
  234.  
  235.         result = add_numbers(result, number);
  236.  
  237.         it1++;
  238.     }
  239.  
  240.     return result;
  241. }
  242.  
  243. BigNum to_decimal(BigNum& num)
  244. {
  245.     BigNum result;
  246.     result.base = 10;
  247.  
  248.     BigNum power{ 10, 1 };
  249.     BigNum base{ 10, num.base };
  250.  
  251.     auto it = num.number.rbegin();
  252.  
  253.     while (it != num.number.rend())
  254.     {
  255.         BigNum tmp{ 10, *it };
  256.         BigNum temp = multiply_numbers(power, tmp);
  257.  
  258.         result = add_numbers(result, temp);
  259.         power = multiply_numbers(power, base);
  260.  
  261.         it++;
  262.     }
  263.  
  264.     return result;
  265. }
  266.  
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement