So, what I basically need is to calculate value of an exponential function (2^n)*(2^(n-1)-1) using c++, where n is a unsigned int type user input. Since n can be assigned any value in unsigned int range, I cannot simply calculate function value and assign it to some unsigned int variable (because resulting number will clearly be out of said range). Therefore, it seems reasonable to me to somehow get my desired function value number by number and write each number as a array element. The only struggle is to realise this method.
Any ideas (both using proposed method or any other one) would be much appreciated.
edit:
Right now I have the following code:
outdated
As expected, it will only work with small values of n
Edit 2: as one of the commentators suggested, I've done some binary numbers by hand. It was pretty fruitful, but I still need sime assistance. Now i have the following code, which will correctly output binary value of said function:
outdated
The only thing left is to convert this value to decimal and hexadecimal. I am not experienced at working with string class, so advice would be appreciated.
Edit 3: Thanks everyone for help. I've completed my program and converted it co C (not willingly, because my professor told me to do so). For anyone interested, the current version of code looks like that:
#include <stdio.h>
#include <stdlib.h>
void binary(unsigned int);
void hex(unsigned int);
void decimal(unsigned int);
int *calculatepower(unsigned int, unsigned int);
void addition(int*, int*, int);
int main(int argc, char** argv){
if (argc != 2){
printf("wrong number of arguments \n");
return -2;
}
unsigned int n = atoi(argv[1]);
printf("exponent - %d \n", n);
binary(n);
hex(n);
decimal(n);
return 0;
}
void binary(unsigned int n){
int i;
printf("binary - ");
for (i=n-1; i>0; i--)
printf("1");
for (i=n; i>0; i--)
printf("0");
printf("\n");
}
void hex(unsigned int nn){
int ones = nn-1;
int zeroes = nn;
int hexzeroes=0, hexfs=0, i;
char switchf, switchzero;
while (zeroes > 3){
hexzeroes+=1;
zeroes-=4;
}
switch (zeroes){
case 0:
break;
case 1:
switchzero='E';
ones-=3;
break;
case 2:
switchzero='C';
ones-=2;
break;
case 3:
switchzero='8';
ones-=1;
break;
default:
break;
}
while (ones>3){
hexfs+=1;
ones-=4;
}
switch (ones){
case 0:
switchf='\0';
break;
case 1:
switchf='1';
break;
case 2:
switchf='3';
break;
case 3:
switchf='7';
break;
default:
break;
}
printf("hexadecimal - %c", switchf);
for (i=0; i<hexfs; i++)
printf("F");
if (zeroes !=0) printf("%c", switchzero);
for (i=0; i<hexzeroes; i++)
printf("0");
printf("\n");
}
void decimal(unsigned int nn){
unsigned int n=nn;
int *str,*powerstr, i, flag=0;
// decimal = 2^n+...+2^((2*n)-1)
unsigned int size = (2*n)/3 + 2;
str = (int*)calloc(size, sizeof(*str));
if(str==NULL)
{
printf("unable to allocate memory");
exit(0);
}
for (i=0; i<size; i++)
{
str[i] = 0;
}
for (n;n<2*nn-1;n++){
powerstr = calculatepower( n, size);
addition(str,powerstr,size);
}
printf("decimal - ");
for (i=0;i<size;i++) {
if ((*(str+i)==0) && (flag==0)){
continue;
}
printf("%d", *(str+i));
flag+=1;
}
}
int *calculatepower(unsigned int n, unsigned int size){
int i, j, buf=0, *powerstr;
powerstr = (int*)calloc(size, sizeof(*powerstr));
for (i=0; i<size; i++)
{
powerstr[i] = 0;
}
powerstr[size-1]=1;
for(j=0;j<n;j++) {
for (i=size-1; i > -1; i--) {
powerstr[i] = powerstr[i] * 2;
if (buf!=0) {
powerstr[i] += 1;
buf=0;
}
if (powerstr[i] > 9) {
buf = 1;
powerstr[i]%=10;
}
}
}
return powerstr;
}
void addition(int *str, int *powerstr, int size){
int i, buf=0;
for (i=size-1; i > -1; i--) {
str[i] = powerstr[i] + str[i];
if (buf!=0) {
str[i] += 1;
buf=0;
}
if (str[i] > 9) {
buf = 1;
str[i]%=10;
}
}
}
Unfortunately, I do not have enough time to polish it. The current biggest problem is not freeing allocated memory and I will fix it later, but I won't update queastion anymore. Thanks again everyone for your answers and comments.
For 16 bit ints it's doable and produces about 40k decimal chars. For 32 bit ints, not so much as it's about 10^20 decimal chars which is beyond anything possible. Even outputting a million chars per second would take longer than the lifetime of the universe.
Here's code for 16 bit ints. Runs in about 3 seconds for n = 65535 not including output time. It has performance improvements by accumulating base 10 sums and normalizing occasionally to prevent overflow.
#include <iostream>
#include <vector>
#include <string>
#include <cstdint>
using std::cout;
using std::vector;
using std::string;
struct BigDecPower2 {
static constexpr uint32_t Normalize_Max{ 26 }; // int8:3, int16:10, int32:26
vector<uint32_t> v;
uint32_t top;
uint32_t normalize_count;
BigDecPower2(uint32_t n) : v(n), top(0), normalize_count(0) {};
void normalize()
{
normalize_count = 0;
for (uint32_t i = 0;; i++)
{
v[i + 1] += v[i] / 10u;
v[i] = v[i] % 10u;
if (i >= top && v[i + 1] == 0)
{
top = i;
return;
}
}
}
void times2() {
for (uint32_t i = 0; i <= top; i++)
v[i] *= 2;
if ((++normalize_count) > Normalize_Max)
normalize();
}
};
void add(BigDecPower2& v1, const BigDecPower2& v2)
{
uint32_t max_top = v1.top > v2.top ? v1.top : v2.top;
for (uint32_t i = 0; i <= max_top; i++)
v1.v[i] += v2.v[i];
if (++v1.normalize_count < v2.normalize_count)
v1.normalize_count = v2.normalize_count;
if (v1.normalize_count > v1.Normalize_Max)
v1.normalize();
}
void print_base(unsigned int n, int number_base)
{
int64_t ones = n-1;
int64_t zeros = n;
if (number_base ==2)
{
while (ones-- > 0)
cout << '1';
while (zeros-- > 0)
cout << '0';
}
else if (number_base == 16) {
int resid = (ones + zeros) % 4;
if (resid == 0)
resid = 4;
cout << "~137F"[resid];
ones -= resid;
while ((ones -= 4) > 0)
cout << 'F';
cout << "8CEF"[ones + 3];
zeros /= 4;
while (zeros--)
cout << '0';
}
else if (number_base == 10)
{
BigDecPower2 v_accum(40000u);
BigDecPower2 v_pwr(40000u); v_pwr.v[0] = 1;
for (uint32_t i = 0; i < n - 1; i++)
{
add(v_accum, v_pwr);
v_pwr.times2();
}
for (uint32_t i = 0; i < n; i++)
v_accum.times2();
v_accum.normalize();
for (uint32_t i = v_accum.top; i != -1; i--)
cout << static_cast<char>(v_accum.v[i] + '0');
}
cout << '\n';
}
int main()
{
// calcs in about 3 seconds, outputs about 40k decimal chars
// print_base(0xffff, 10);
// Demo
for (int i = 1; i < 10; i++)
{
print_base(i, 2);
print_base(i, 16);
print_base(i, 10);
cout << '\n';
}
}
You can use unsigned long or unsigned long long (or uintX_t where X is the maximum supported size on your platform) if unsigned int cannot hold your output. If that's still not enough for your use case, then either implement your own big integer class, or use an existing library (recommended if you can afford it). There are a couple of them out there. For example, GNU Multiple Precision Arithmetic Library (GMP) and bigint-library. See this list for more.
In case you decided to go on your own and implement your own class, this might give you some clues on how to start. (Note that, for efficiency matters, number theory algorithms may be applied. It is not an easy task to come with a good implementation).
template<typename T = unsigned, int Base = 10> class Bigint {
std::vector<T> digits;
bool sign; // For e.g. true for + or 0, false for -
public:
Bigint() : digits(), sign(true) { }
Bigint(int x)
{
// Insert digits of x into digits vector
// Don't forget the sign
}
// Do the same with other types: short, long, unsigned, etc.
Bigint(const char *x)
{
// You need to parse x. Bad formatting is to be handled (tip: use exceptions)
}
// Provide an std::string version
Bigint(const Bigint& bi) : digits(bi.digits), sign(bi.sign) {}
Bigint& operator=(const Bigint& bi)
{
// Copy...
return *this;
}
// You also have to implement operators
Bigint& operator+(const Bigint& bi)
{
// Logic...
return *this;
}
// Other operators: -, /, %, bitwise, etc.
// Tip: you can use a helper class to be used by both / and % since they share a similar logic (for avoiding redundant code).
Bigint power(const Bigint& bi) // Provide other signatures: int, string, etc.
{
// Logic...
}
};
Related
I need to permute N numbers between 0 and N-1 in the fastest way (on a CPU, without multi-threading, but maybe with SIMD). N is not large, I think in most cases, N<=12, so N! fits a signed 32-bit integer.
What I have tried so far is roughly the following (some optimizations are omitted, and my original code is in Java, but we speak performance in C++ if not pseudo-code):
#include <random>
#include <cstdint>
#include <iostream>
static inline uint64_t rotl(const uint64_t x, int k) {
return (x << k) | (x >> (64 - k));
}
static uint64_t s[2];
uint64_t Next(void) {
const uint64_t s0 = s[0];
uint64_t s1 = s[1];
const uint64_t result = rotl(s0 + s1, 17) + s0;
s1 ^= s0;
s[0] = rotl(s0, 49) ^ s1 ^ (s1 << 21); // a, b
s[1] = rotl(s1, 28); // c
return result;
}
// Assume the array |dest| must have enough space for N items
void GenPerm(int* dest, const int N) {
for(int i=0; i<N; i++) {
dest[i] = i;
}
uint64_t random = Next();
for(int i=0; i+1<N; i++) {
const int ring = (N-i);
// I hope the compiler optimizes acquisition
// of the quotient and modulo for the same
// dividend and divisor pair into a single
// CPU instruction, at least in Java it does
const int pos = random % ring + i;
random /= ring;
const int t = dest[pos];
dest[pos] = dest[i];
dest[i] = t;
}
}
int main() {
std::random_device rd;
uint32_t* seed = reinterpret_cast<uint32_t*>(s);
for(int i=0; i<4; i++) {
seed[i] = rd();
}
int dest[20];
for(int i=0; i<10; i++) {
GenPerm(dest, 12);
for(int j=0; j<12; j++) {
std::cout << dest[j] << ' ';
}
std::cout << std::endl;
}
return 0;
}
The above is slow because the CPU's modulo operation (%) is slow. I could think of generating one random number between 0 and N!-1 (inclusive); this will reduce the number of modulo operations and Next() calls, but I don't know how to proceed then. Another approach could be to replace the division operation with multiplication by the inverse integer number at the cost of small bias in the modulos generated, but I don't these inverse integers and multiplication will probably not be much faster (bitwise operations & shifts should be faster).
Any more concrete ideas?
UPDATE: I've been asked why it's a bottleneck in the real application. So I just posted a task that may be of interest to the other folks. The real task in production is:
struct Item {
uint8_t is_free_; // 0 or 1
// ... other members ...
};
Item* PickItem(const int time) {
// hash-map lookup, non-empty arrays
std::vector<std::vector<Item*>>> &arrays = GetArrays(time);
Item* busy = nullptr;
for(int i=0; i<arrays.size(); i++) {
uint64_t random = Next();
for(int j=0; j+1<arrays[i].size(); j++) {
const int ring = (arrays[i].size()-j);
const int pos = random % ring + j;
random /= ring;
Item *cur = arrays[i][pos];
if(cur.is_free_) {
// Return a random free item from the first array
// where there is at least one free item
return cur;
}
arrays[i][pos] = arrays[i][j];
arrays[i][j] = cur;
}
Item* cur = arrays[i][arrays[i].size()-1];
if(cur.is_free_) {
return cur;
} else {
// Return the busy item in the last array if no free
// items are found
busy = cur;
}
}
return busy;
}
I came up with the following solution in C++ (though not very portable to Java, because Java doesn't allow parametrizing generics with a constant - in Java I had to use polymorphism, as well as a lot of code duplication):
#include <random>
#include <cstdint>
#include <iostream>
static inline uint64_t rotl(const uint64_t x, int k) {
return (x << k) | (x >> (64 - k));
}
static uint64_t s[2];
uint64_t Next(void) {
const uint64_t s0 = s[0];
uint64_t s1 = s[1];
const uint64_t result = rotl(s0 + s1, 17) + s0;
s1 ^= s0;
s[0] = rotl(s0, 49) ^ s1 ^ (s1 << 21); // a, b
s[1] = rotl(s1, 28); // c
return result;
}
template<int N> void GenPermInner(int* dest, const uint64_t random) {
// Because N is a constant, the compiler can optimize the division
// by N with more lightweight operations like shifts and additions
const int pos = random % N;
const int t = dest[pos];
dest[pos] = dest[0];
dest[0] = t;
return GenPermInner<N-1>(dest+1, random / N);
}
template<> void GenPermInner<0>(int*, const uint64_t) {
return;
}
template<> void GenPermInner<1>(int*, const uint64_t) {
return;
}
// Assume the array |dest| must have enough space for N items
void GenPerm(int* dest, const int N) {
switch(N) {
case 0:
case 1:
return;
case 2:
return GenPermInner<2>(dest, Next());
case 3:
return GenPermInner<3>(dest, Next());
case 4:
return GenPermInner<4>(dest, Next());
case 5:
return GenPermInner<5>(dest, Next());
case 6:
return GenPermInner<6>(dest, Next());
case 7:
return GenPermInner<7>(dest, Next());
case 8:
return GenPermInner<8>(dest, Next());
case 9:
return GenPermInner<9>(dest, Next());
case 10:
return GenPermInner<10>(dest, Next());
case 11:
return GenPermInner<11>(dest, Next());
case 12:
return GenPermInner<12>(dest, Next());
// You can continue with larger numbers, so long as (N!-1) fits 64 bits
default: {
const uint64_t random = Next();
const int pos = random % N;
const int t = dest[pos];
dest[pos] = dest[0];
dest[0] = t;
return GenPerm(dest+1, N-1);
}
}
}
int main() {
std::random_device rd;
uint32_t* seed = reinterpret_cast<uint32_t*>(s);
for(int i=0; i<4; i++) {
seed[i] = rd();
}
int dest[20];
const int N = 12;
// No need to init again and again
for(int j=0; j<N; j++) {
dest[j] =j;
}
for(int i=0; i<10; i++) {
GenPerm(dest, N);
// Or, if you know N at compile-time, call directly
// GenPermInner<N>(dest, Next());
for(int j=0; j<N; j++) {
std::cout << dest[j] << ' ';
}
std::cout << std::endl;
}
return 0;
}
I have been practicing median search algorithm, and this is what I wrote-
#include <iostream>
#include <stdlib.h>
using namespace std;
int S1[10] = { 0 };
int S2[1] = { 0 };
int S3[10] = { 0 };
int mediansearch(int A[], int k, int size)
{
int ran = rand() % size;
int i = 0;
int a = 0;
int b = 0;
int c = 0;
for (i = 0; i < size; i++)
{
if (A[ran] > A[i])
{
S1[a] = A[i];
a++;
}
else if (A[ran] == A[i])
{
S2[b] = A[i];
b++;
}
else
{
S3[c] = A[i];
c++;
}
}
if (a <= k)
{
return mediansearch(S1, k, a);
}
else if (a + b <= k)
{
return A[ran];
}
else
{
return mediansearch(S3, k - a - b, c);
}
}
int main()
{
int arr[] = { 6, 5, 4, 8, 99, 74, 23 };
int n = sizeof(arr) / sizeof(arr[0]);
int x = mediansearch(arr, 5, n);
cout << "5th smallest is:" << x << endl;
}
And I have been getting output as-
Process returned -1073741676 (0xC0000094) execution time : 1.704 s
So, what am I doing wrong? Any kind of help will be appreciated.
There are a few issues with this code, the first one being the naming of variables.
I suggest you choose more significative names in the future, because good naming is fundamental when someone else has to understand your code and your ideas.
Another thing is that the arguments of are in a counterintuitive order because the pair related to the array are separated by the index you want to look for.
I'd write int mediansearch(int A[], int size, int k)
Here the comparisons are reversed, k should be less than rather than greater than equal a
if (a <= k) // (k < a)
{
return mediansearch(S1, k, a);
}
else if (a + b <= k) // (k < a + b)
{
return A[ran];
}
else
{
return mediansearch(S3, k - a - b, c);
}
The other thing is that you're sharing S1, S2, and S3 among all the recursive calls and that causes some error that I wasn't able to identify, maybe someone commenting will help me out.
However, I suggest you read this article that explains in detail the procedure you're trying to implement: https://rcoh.me/posts/linear-time-median-finding/
It's python, but it can be easily ported to C/C++, and in fact that's what I did.
#include <iostream>
#include <stdlib.h>
#include <assert.h>
#include <time.h>
using namespace std;
int medianSearch(int A[], int size, int k)
{
int *lows = (int *)calloc(size, sizeof(int));
int lowsLen = 0;
int *highs = (int *)calloc(size, sizeof(int));
int highsLen = 0;
int *pivots = (int *)calloc(size, sizeof(int));
int pivotsLen = 0;
int median;
int pivot;
int i;
if (size == 1)
return A[0];
// Other ways of randomly picking a pivot
// pivot = 0;
// pivot = size-1;
// pivot = size/2;
assert(size > 0);
pivot = rand() % size;
for (i = 0; i < size; ++i)
{
if (A[i] < A[pivot])
{
lows[lowsLen] = A[i];
lowsLen++;
}
else if (A[i] > A[pivot])
{
highs[highsLen] = A[i];
highsLen++;
}
else
{
pivots[pivotsLen] = A[i];
pivotsLen++;
}
}
if (k < lowsLen)
median = medianSearch(lows, lowsLen, k);
else if (k < lowsLen + pivotsLen)
median = A[pivot];
else
median = medianSearch(highs, highsLen, k - lowsLen - pivotsLen);
free(lows);
free(highs);
free(pivots);
return median;
}
int compare(const void *a, const void *b)
{
return ( *(int *)a - *(int *)b );
}
int medianSorted(int A[], int size, int k)
{
qsort(A, size, sizeof(int), compare);
return A[k];
}
#define N 1000
int main()
{
int arr[N];
int brr[N];
int n = sizeof(arr) / sizeof(arr[0]);
int k = 200;
int x;
int y;
for (int i = 0; i < n; ++i)
arr[i] = brr[i] = rand();
x = medianSearch(arr, n, (k-1)%n);
y = medianSorted(brr, n, (k-1)%n);
string suffix;
switch (k % 10)
{
case 1: suffix = "st"; break;
case 2: suffix = "nd"; break;
case 3: suffix = "rd"; break;
case 4:
case 5:
case 6:
case 7:
case 8:
case 9:
case 0: suffix = "th"; break;
}
cout << k << suffix << " smallest is: " << x << endl;
cout << k << suffix << " smallest is: " << y << endl;
}
https://onlinegdb.com/HJc2V6Lbu
I'm wanting to print an int array with 8 bytes and convert it to bin & hex with the output as such:
0 00000000 00
1 00000001 07
...
I've finished creating the binary convert function. I want to use the same function as the binary conversion -with an array, but check the left half with the right half and solve each different sided of the 8 bytes; left most -3 and right most is -7.
What am I doing wrong? I cannot figure out how to implement it and I know my hex function is all out of wack.
#include <iostream>
#include <string>
#include <math.h>
using namespace std;
const int num = 8; //may not be needed -added for hex
void Generatebinary(int arr[]);
void GeneratehexDec(int arr[]);
void print_binary(int arr[]); //haven't created yet
int main()
{
int arr[8] = { 0, 0, 0, 0, 0, 0, 0, 0 };
int i = 1;
while (i < 256)
{
Generatebinary(arr);
print_binary(arr); //not created yet
GeneratehexDec(arr);
i++;
}
}
void Generatebinary(int arr[])
{
for (int i = 7; i > 0; i--)
{
if (arr[i] == 1)
arr[i] = 0;
else if (arr[i] == 0)
{
arr[i] = 1;
break;
}
}
}
void GereatehexDec(int num)
{ //improper use
int a;
int i;
int answer[] = { };
a = num % 16;
i++;
answer[i] = num;
for (int i = num; i > 0; i--)
{
cout << answer[i];
}
cout << a;
}
First of all, you can't do int answer[] = { }; an array has to be pre-allocated (indicating how many elements it will store) or has to be dynamically allocated during run-time, then be freed, you have to manage your memory, not forget to deallocate... It's for this reason that Stroustrup tells you to not use arrays unless necessary. Use std::vector
void GereatehexDec(int num)
{ //improper use
int a = 0; // always initialize your variables
int i = 0; // is this i supposed to be the same as the i in the for loop below?
std::vector<int> answer;
a = num % 16;
i++; // this doesn't make sense
answer.at(i) = num;
for (int i = num; i > 0; i--) // what about the i variable you declared previously?
{
cout << answer.at(i);
}
cout << a;
}
Here's a template function that could help you (converts numbers into string hex)
template <typename I> std::string n2hexstr(I w, size_t hex_len = sizeof(I) << 1) {
static const char* digits = "0123456789ABCDEF";
std::string rc(hex_len, '0');
for (size_t i = 0, j = (hex_len - 1) * 4; i<hex_len; ++i, j -= 4)
rc[i] = digits[(w >> j) & 0x0f];
return "0x" + rc;
}
int main() {
std::cout << n2hexstr(127);
}
i am a beginner to c++ but i wouldn't have asked this question if i didnt spend hours on it.
The code is about finding primes between two numbers in the most efficient way where maximum limit is 10^9.
The following code gives me runtime error but i have no idea why.. help
#include <iostream>
#include <stdio.h>
#include <math.h>
using namespace std;
long int prime[32000];
bool isprime(long int a){
for(long int i = 3; i <= 32000; i+=2){
if(a%i == 0){
return false;
}
}
return true;
}
void generateprimes(){
long int a = 0;
for(long int i = 3; i < 31623 ; i+=2){
if(isprime(i)){
prime[a] = i;
a++;
}
}
}
bool newisprime(long int a){
long int x =0;
for(long int i = prime[x]; i <= sqrt(a); i = prime[++x]){
if(a%i == 0){
return false;
}
}
return true;
}
void generateprimes_inbetween(long int n,long int m){
if(n%2 == 0){
++n;
}
if(n == 1){
printf("2\n");
n = 3;
}
for(long int i = n; i <= m ; i+=2){
if(newisprime(i)){
printf("%d\n",i);
}
}
}
int main() {
long int a,b,c;
scanf("%ld",&a);
generateprimes();
for(long int i = 0; i < a ; i++){
scanf("%ld %ld",&b,&c);
generateprimes_inbetween(b,c);
printf("\n");
}
return 0;
}
In isprime() you loop through ALL numbers in your array prime[]. But at startup, as it's global data, most of them will be 0, so that a%i will result in a fatal divide by 0.
You have somewhere to keep track of the numer of primes that you've stored in your array and only test against the primes that you've stored there.
Supposing that it's homework and you're not allowed to use vectors, you could do it as follows:
const size_t max_primes = 32000; // avoid hard coded values
unsigned long prime[max_primes] {2, 3}; // prefilled values
size_t nprimes = 2; // number of primes in the array
bool isprime(unsigned long a){
for(size_t i = 0; i < nprimes; i++){
if(a%prime[i] == 0)
return false;
}
return true;
}
void generateprimes(){
nprimes = 2;
for(unsigned long i = 3; nprimes<max_primes && i < ULONG_MAX; i += 2){
if(isprime(i)){
prime[nprimes] = i;
nprimes++;
}
}
}
bool newisprime(unsigned long a){
size_t x = 0;
for(unsigned long i = prime[x]; i <= sqrt(a) && x<nprimes; i = prime[++x]){
if(a%i == 0)
return false;
}
if(x == nprimes) {
cout << "Attention: Reaching end of prime table !!" << endl;
}
return true;
}
Some remarks:
for the index, it's safer to use the unsigned type size_t.
make sure that whenever you use an index, it remains within the bounds
as you work with positive numbers, it could make sense to use unsigned long
Here I've got a bigint calculator that uses a safearray class(not shown) to store large numbers and do arithmetic operations on them. I've got add and subtract working but when I try multiplication it compiles and runs but nothing happens. Could someone help me fix this? Thanks
int size = 100;
class bigint
{
SafeArray<int> *arr;
public:
char sign;
bigint() //initializes to zero
{
arr = new SafeArray<int>;
for(int i =0;i < size; i++)
arr->set(i,0);
}
void print() //prints numbers without zeroes in front
{
bool start_num=false;
for(int i = 0;i <arr->get_size() ;i++)
{
if(arr->get(i)!=0 && start_num==false )
{start_num=true;
cout << arr->get(i);}
else if(start_num==true)
cout<<arr->get(i);
}
cout<<endl;
}
void assign(const bigint &A) //
{
for(int i=0;i<arr->get_size();i++)
{ //Ways to initialize stuff
arr->set(i,A.arr->get(i));
}
}
void assign(int num) //
{
for(int i = arr->get_size()- 1; i >= 0; i--)
{
arr->set(i,num%10);
num /=10;
}
}
void assign(string num) //
{
long len = num.length();
int j=arr->get_size()-1;
for(long i=len-1;i>=0;i--)
{
arr->set(j,num[i]-48);
j--;
}
}
void add_pos(const bigint &A) //add big ints
{
int carry=0;
for(int i=size-1;i>=0;i--)
{
int result = arr->get(i)+A.arr->get(i)+carry;
arr->set(i,result%10);
carry=result/10;
}
}
void multiply(bigint &A)
{
bigint temp;
for(int i=0;i<size;i +=1)
{
temp.arr->set(i,arr->get(i));
arr->set(i,0);
}
int i1, i2;
for(i2=0; i2<size; i2++)
{
int borrow =0;
for(i1=0;i1+i2<size;i1++)
{
int total=temp.arr->get(i1)*A.arr->get(i2);
int totalsum=total+arr->get(i1+i2)+borrow;
arr->set(i1+i2,totalsum%10);
borrow = totalsum/10;
}
}
};
int main()
{
bigint a, b, c;
a.assign("2543281");
b.assign("3434");
a.mulitply(b);
a.print();
return 0;
}
The result of multiplication of two bigint numbers of size = 100 certainly needs more than 100 digits, perhaps 200?
For minimal modification, you may pass size as constructor argument to bigint. Ideally, bigint may use a vector so that the digit array can grow dynamically in a convenient and flexible way.
class bigint {
std::vector<int8_t> digits_; // each digit must be in 0-9 range
...
These were lil complicated so I came up with this:
InfInt InfInt::operator*(const InfInt& a) const{
InfInt final = 0;
std::string result;
InfInt* temp;
int carry;
int current;
//fast mult algorithm. the same we were taught in elementary.
for(long i=length() - 1;i >= 0; i--){
carry = 0;
result = "";
for (long j=a.length() - 1; j >= 0; j--){
current = (value[i] - '0') * (a.value[j] - '0') + carry;
result = (char)(current % 10 + '0') + result;
carry = current / 10;
}
if (carry > 0)
result = (char)(carry + '0') + result;
temp = new InfInt(result);
final += *new InfInt(temp->alignLeft(length() - i - 1));
}
final.setSign(sign ^ a.sign);
return final;
}
Hope it helps