Figure out if a very large number is divisible by another - c++

I am dealing with a programming question where I need to divide a very big number, of the order of 10^50000 by another of the order of 1000, in order to figure out if one is divisible by the other. So I need to use strings to store this large number.
I don't know any method to divide a string by a number. Can anyone point me to an algorithm?

Here is a start of an algorithm. It seems to do what you are asking for: it performs "long division" in 4 character chunks, and keeps track of the remainder. It prints the remainder at the end. You should be able to adapt this to your specific needs. Note - doing this in 4 bytes chunks makes it significantly faster than conventional one-character-at-a-time algorithms, but it does rely on b being small enough to fit in an int (hence the 4 character chunks).
#include <stdio.h>
#include <string.h>
int main(void) {
char as[]="123123123123126";
int l = strlen(as);
int rem;
int lm = l % 4; // the size of the initial chunk (after which we work in multiples of 4)
char *ap=as; // a pointer to keep track of "where we are in the string"
int b=123; // the divisor
int a;
sscanf(ap, "%4d", &a);
while(lm++ < 4) a /= 10;
// printf("initial a is %d\n", a);
rem = a % b;
for(ap = as + (l%4); ap < as + l; ap += 4) {
// printf("remainder = %d\n", rem);
sscanf(ap, "%4d", &a);
// printf("a is now %d\n", a);
rem = (a + 10000*rem) %b;
}
printf("remainder is %d\n", rem);
return 0;
}
Output:
remainder is 3
This needs some cleaning up but I hope you get the idea.

Related

Floating point error in C++ code

I am trying to solve a question in which i need to find out the number of possible ways to make a team of two members.(note: a team can have at most two person)
After making this code, It works properly but in some test cases it shows floating point error ad i can't find out what it is exactly.
Input: 1st line : Number of test cases
2nd line: number of total person
Thank you
#include<iostream>
using namespace std;
long C(long n, long r)
{
long f[n + 1];
f[0] = 1;
for (long i = 1; i <= n; i++)
{
f[i] = i * f[i - 1];
}
return f[n] / f[r] / f[n - r];
}
int main()
{
long n, r, m,t;
cin>>t;
while(t--)
{
cin>>n;
r=1;
cout<<C(n, min(r, n - r))+1<<endl;
}
return 0;
}
You aren't getting a floating point exception. You are getting a divide by zero exception. Because your code is attempting to divide by the number 0 (which can't be done on a computer).
When you invoke C(100, 1) the main loop that initializes the f array inside C increases exponentially. Eventually, two values are multiplied such that i * f[i-1] is zero due to overflow. That leads to all the subsequent f[i] values being initialized to zero. And then the division that follows the loop is a division by zero.
Although purists on these forums will say this is undefined, here's what's really happening on most 2's complement architectures. Or at least on my computer....
At i==21:
f[20] is already equal to 2432902008176640000
21 * 2432902008176640000 overflows for 64-bit signed, and will typically become -4249290049419214848 So at this point, your program is bugged and is now in undefined behavior.
At i==66
f[65] is equal to 0x8000000000000000. So 66 * f[65] gets calculated as zero for reasons that make sense to me, but should be understood as undefined behavior.
With f[66] assigned to 0, all subsequent assignments of f[i] become zero as well. After the main loop inside C is over, the f[n-r] is zero. Hence, divide by zero error.
Update
I went back and reverse engineered your problem. It seems like your C function is just trying to compute this expression:
N!
-------------
R! * (N-R)!
Which is the "number of unique sorted combinations"
In which case instead of computing the large factorial of N!, we can reduce that expression to this:
n
[ ∏ i ]
n-r
--------------------
R!
This won't eliminate overflow, but will allow your C function to be able to take on larger values of N and R to compute the number of combinations without error.
But we can also take advantage of simple reduction before trying to do a big long factorial expression
For example, let's say we were trying to compute C(15,5). Mathematically that is:
15!
--------
10! 5!
Or as we expressed above:
1*2*3*4*5*6*7*8*9*10*11*12*13*14*15
-----------------------------------
1*2*3*4*5*6*7*8*9*10 * 1*2*3*4*5
The first 10 factors of the numerator and denominator cancel each other out:
11*12*13*14*15
-----------------------------------
1*2*3*4*5
But intuitively, you can see that "12" in the numerator is already evenly divisible by denominators 2 and 3. And that 15 in the numerator is evenly divisible by 5 in the denominator. So simple reduction can be applied:
11*2*13*14*3
-----------------------------------
1 * 4
There's even more room for greatest common divisor reduction, but this is a great start.
Let's start with a helper function that computes the product of all the values in a list.
long long multiply_vector(std::vector<int>& values)
{
long long result = 1;
for (long i : values)
{
result = result * i;
if (result < 0)
{
std::cout << "ERROR - multiply_range hit overflow" << std::endl;
return 0;
}
}
return result;
}
Not let's implement C as using the above function after doing the reduction operation
long long C(int n, int r)
{
if ((r >= n) || (n < 0) || (r < 0))
{
std::cout << "invalid parameters passed to C" << std::endl;
return 0;
}
// compute
// n!
// -------------
// r! * (n-r)!
//
// assume (r < n)
// Which maps to
// n
// [∏ i]
// n - r
// --------------------
// R!
int end = n;
int start = n - r + 1;
std::vector<int> numerators;
std::vector<int> denominators;
long long numerator = 1;
long long denominator = 1;
for (int i = start; i <= end; i++)
{
numerators.push_back(i);
}
for (int i = 2; i <= r; i++)
{
denominators.push_back(i);
}
size_t n_length = numerators.size();
size_t d_length = denominators.size();
for (size_t n = 0; n < n_length; n++)
{
int nval = numerators[n];
for (size_t d = 0; d < d_length; d++)
{
int dval = denominators[d];
if ((nval % dval) == 0)
{
denominators[d] = 1;
numerators[n] = nval / dval;
}
}
}
numerator = multiply_vector(numerators);
denominator = multiply_vector(denominators);
if ((numerator == 0) || (denominator == 0))
{
std::cout << "Giving up. Can't resolve overflow" << std::endl;
return 0;
}
long long result = numerator / denominator;
return result;
}
You are not using floating-point. And you seem to be using variable sized arrays, which is a C feature and possibly a C++ extension but not standard.
Anyway, you will get overflow and therefore undefined behaviour even for rather small values of n.
In practice the overflow will lead to array elements becoming zero for not much larger values of n.
Your code will then divide by zero and crash.
They also might have a test case like (1000000000, 999999999) which is trivial to solve, but not for your code which I bet will crash.
You don't specify what you mean by "floating point error" - I reckon you are referring to the fact that you are doing an integer division rather than a floating point one so that you will always get integers rather than floats.
int a, b;
a = 7;
b = 2;
std::cout << a / b << std::endl;
this will result in 3, not 3.5! If you want floating point result you should use floats instead like this:
float a, b;
a = 7;
b = 2;
std::cout << a / b << std::end;
So the solution to your problem would simply be to use float instead of long long int.
Note also that you are using variable sized arrays which won't work in C++ - why not use std::vector instead??
Array syntax as:
type name[size]
Note: size must a constant not a variable
Example #1:
int name[10];
Example #2:
const int asize = 10;
int name[asize];

factorial of big numbers with strings in c++

I am doing a factorial program with strings because i need the factorial of Numbers greater than 250
I intent with:
string factorial(int n){
string fact="1";
for(int i=2; i<=n; i++){
b=atoi(fact)*n;
}
}
But the problem is that atoi not works. How can i convert my string in a integer.
And The most important Do I want to know if the program of this way will work with the factorial of 400 for example?
Not sure why you are trying to use string. Probably to save some space by not using integer vector? This is my solution by using integer vector to store factorial and print.Works well with 400 or any large number for that matter!
//Factorial of a big number
#include<iostream>
#include<vector>
using namespace std;
int main(){
int num;
cout<<"Enter the number :";
cin>>num;
vector<int> res;
res.push_back(1);
int carry=0;
for(int i=2;i<=num;i++){
for(int j=0;j<res.size();j++){
int tmp=res[j]*i;
res[j]=(tmp+carry)%10 ;
carry=(tmp+carry)/10;
}
while(carry!=0){
res.push_back(carry%10);
carry=carry/10;
}
}
for(int i=res.size()-1;i>=0;i--) cout<<res[i];
cout<<endl;
return 0;
}
Enter the number :400
Factorial of 400 :64034522846623895262347970319503005850702583026002959458684445942802397169186831436278478647463264676294350575035856810848298162883517435228961988646802997937341654150838162426461942352307046244325015114448670890662773914918117331955996440709549671345290477020322434911210797593280795101545372667251627877890009349763765710326350331533965349868386831339352024373788157786791506311858702618270169819740062983025308591298346162272304558339520759611505302236086810433297255194852674432232438669948422404232599805551610635942376961399231917134063858996537970147827206606320217379472010321356624613809077942304597360699567595836096158715129913822286578579549361617654480453222007825818400848436415591229454275384803558374518022675900061399560145595206127211192918105032491008000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
There's a web site that will calculate factorials for you: http://www.nitrxgen.net/factorialcalc.php. It reports:
The resulting factorial of 250! is 493 digits long.
The result also contains 62 trailing zeroes (which constitutes to 12.58% of the whole number)
3232856260909107732320814552024368470994843717673780666747942427112823747555111209488817915371028199450928507353189432926730931712808990822791030279071281921676527240189264733218041186261006832925365133678939089569935713530175040513178760077247933065402339006164825552248819436572586057399222641254832982204849137721776650641276858807153128978777672951913990844377478702589172973255150283241787320658188482062478582659808848825548800000000000000000000000000000000000000000000000000000000000000
Many systems using C++ double only work up to 1E+308 or thereabouts; the value of 250! is too large to store in such numbers.
Consequently, you'll need to use some sort of multi-precision arithmetic library, either of your own devising using C++ string values, or using some other widely-used multi-precision library (GNU GMP for example).
The code below uses unsigned double long to calculate very large digits.
#include<iostream.h>
int main()
{
long k=1;
while(k!=0)
{
cout<<"\nLarge Factorial Calculator\n\n";
cout<<"Enter a number be calculated:";
cin>>k;
if (k<=33)
{
unsigned double long fact=1;
fact=1;
for(int b=k;b>=1;b--)
{
fact=fact*b;
}
cout<<"\nThe factorial of "<<k<<" is "<<fact<<"\n";
}
else
{
int numArr[10000];
int total,rem=0,count;
register int i;
//int i;
for(i=0;i<10000;i++)
numArr[i]=0;
numArr[10000]=1;
for(count=2;count<=k;count++)
{
while(i>0)
{
total=numArr[i]*count+rem;
rem=0;
if(total>9)
{
numArr[i]=total%10;
rem=total/10;
}
else
{
numArr[i]=total;
}
i--;
}
rem=0;
total=0;
i=10000;
}
cout<<"The factorial of "<<k<<" is \n\n";
for(i=0;i<10000;i++)
{
if(numArr[i]!=0 || count==1)
{
cout<<numArr[i];
count=1;
}
}
cout<<endl;
}
cout<<"\n\n";
}//while
return 0;
}
Output:
![Large Factorial Calculator
Enter a number be calculated:250
The factorial of 250 is
32328562609091077323208145520243684709948437176737806667479424271128237475551112
09488817915371028199450928507353189432926730931712808990822791030279071281921676
52724018926473321804118626100683292536513367893908956993571353017504051317876007
72479330654023390061648255522488194365725860573992226412548329822048491377217766
50641276858807153128978777672951913990844377478702589172973255150283241787320658
18848206247858265980884882554880000000000000000000000000000000000000000000000000
000000000000][1]
You can make atoi compile by adding c_str(), but it will be a long way to go till getting factorial. Currently you have no b around. And if you had, you still multiply int by int. So even if you eventually convert that to string before return, your range is still limited. Until you start to actually do multiplication with ASCII or use a bignum library there's no point to have string around.
Your factorial depends on conversion to int, which will overflow pretty fast, so you want be able to compute large factorials that way. To properly implement computation on big numbers you need to implement logic as for computation on paper, rules that you were tought in primary school, but treat long long ints as "atoms", not individual digits. And don't do it on strings, it would be painfully slow and full of nasty conversions
If you are going to solve factorial for numbers larger than around 12, you need a different approach than using atoi, since that just gives you a 32-bit integer, and no matter what you do, you are not going to get more than 2 billion (give or take) out of that. Even if you double the size of the number, you'll only get to about 20 or 21.
It's not that hard (relatively speaking) to write a string multiplication routine that takes a small(ish) number and multiplies each digit and ripples the results through to the the number (start from the back of the number, and fill it up).
Here's my obfuscated code - it is intentionally written such that you can't just take it and hand in as school homework, but it appears to work (matches the number in Jonathan Leffler's answer), and works up to (at least) 20000! [subject to enough memory].
std::string operator*(const std::string &s, int x)
{
int l = (int)s.length();
std::string r;
r.resize(l);
std::fill(r.begin(), r.end(), '0');
int b = 0;
int e = ~b;
const int c = 10;
for(int i = l+e; i != e;)
{
int d = (s[i]-0x30) * x, p = i + b;
while (d && p > e)
{
int t = r[p] - 0x30 + (d % c);
r[p] = (t % c) + 0x30;
d = t / c + d / c;
p--;
}
while (d)
{
r = static_cast<char>((d % c) +0x30)+r;
d /= c;
b++;
}
i--;
}
return r;
}
In C++, the largest integer type is 'long long', and it hold 64 bits of memory, so obviously you can't store 250! in an integer type. It is a clever idea to use strings, but what you are basically doing with your code is (I have never used the atoi() function, so I don't know if it even works with strings larger than 1 character, but it doesn't matter):
covert the string to integer (a string that if this code worked well, in one moment contains the value of 249!)
multiply the value of the string
So, after you are done multiplying, you don't even convert the integer back to string. And even if you did that, at one moment when you convert the string back to an integer, your program will crash, because the integer won't be able to hold the value of the string.
My suggestion is, to use some class for big integers. Unfortunately, there isn't one available in C++, so you'll have to code it by yourself or find one on the internet. But, don't worry, even if you code it by yourself, if you think a little, you'll see it's not that hard. You can even use your idea with the strings, which, even tough is not the best approach, for this problem, will still yield the results in the desired time not using too much memory.
This is a typical high precision problem.
You can use an array of unsigned long long instead of string.
like this:
struct node
{
unsigned long long digit[100000];
}
It should be faster than string.
But You still can use string unless you are urgent.
It may take you a few days to calculate 10000!.
I like use string because it is easy to write.
#include <bits/stdc++.h>
#pragma GCC optimize (2)
using namespace std;
const int MAXN = 90;
int n, m;
int a[MAXN];
string base[MAXN], f[MAXN][MAXN];
string sum, ans;
template <typename _T>
void Swap(_T &a, _T &b)
{
_T temp;
temp = a;
a = b;
b = temp;
}
string operator + (string s1, string s2)
{
string ret;
int digit, up = 0;
int len1 = s1.length(), len2 = s2.length();
if (len1 < len2) Swap(s1, s2), Swap(len1, len2);
while(len2 < len1) s2 = '0' + s2, len2++;
for (int i = len1 - 1; i >= 0; i--)
{
digit = s1[i] + s2[i] - '0' - '0' + up; up = 0;
if (digit >= 10) up = digit / 10, digit %= 10;
ret = char(digit + '0') + ret;
}
if (up) ret = char(up + '0') + ret;
return ret;
}
string operator * (string str, int p)
{
string ret = "0", f; int digit, mul;
int len = str.length();
for (int i = len - 1; i >= 0; i--)
{
f = "";
digit = str[i] - '0';
mul = p * digit;
while(mul)
{
digit = mul % 10 , mul /= 10;
f = char(digit + '0') + f;
}
for (int j = 1; j < len - i; j++) f = f + '0';
ret = ret + f;
}
return ret;
}
int main()
{
freopen("factorial.out", "w", stdout);
string ans = "1";
for (int i = 1; i <= 5000; i++)
{
ans = ans * i;
cout << i << "! = " << ans << endl;
}
return 0;
}
Actually, I know where the problem raised At the point where we multiply , there is the actual problem ,when numbers get multiplied and get bigger and bigger.
this code is tested and is giving the correct result.
#include <bits/stdc++.h>
using namespace std;
#define mod 72057594037927936 // 2^56 (17 digits)
// #define mod 18446744073709551616 // 2^64 (20 digits) Not supported
long long int prod_uint64(long long int x, long long int y)
{
return x * y % mod;
}
int main()
{
long long int n=14, s = 1;
while (n != 1)
{
s = prod_uint64(s , n) ;
n--;
}
}
Expexted output for 14! = 87178291200
The logic should be:
unsigned int factorial(int n)
{
unsigned int b=1;
for(int i=2; i<=n; i++){
b=b*n;
}
return b;
}
However b may get overflowed. So you may use a bigger integral type.
Or you can use float type which is inaccurate but can hold much bigger numbers.
But it seems none of the built-in types are big enough.

Sieve of Eratosthenes algorithm not working for large limits

I have programmed a sieve of Eratosthenes algorithm in C++, and it works fine for smaller numbers that I have tested it with. However, when I use large numbers, i.e. 2 000 000 as the upper limit, the program begins giving wrong answers. Can anyone clarify why?
Your help is appreciated.
#include <iostream>
#include <time.h>
using namespace std;
int main() {
clock_t a, b;
a = clock();
int n = 0, k = 2000000; // n = Sum of primes, k = Upper limit
bool r[k - 2]; // r = All numbers below k and above 1 (if true, it has been marked as a non-prime)
for(int i = 0; i < k - 2; i++) // Check all numbers
if(!r[i]) { // If it hasn't been marked as a non-prime yet ...
n += i + 2; // Add the prime to the total sum (+2 because of the shift - index 0 is 2, index 1 is 3, etc.)
for(int j = 2 * i + 2; j < k - 2; j += i + 2) // Go through all multiples of the prime under the limit
r[j] = true; // Mark the multiple as a non-prime
}
b = clock();
cout << "Final Result: " << n << endl;
cout << b - a << "ms runtime achieved." << endl;
return 0;
}
EDIT: I just did some debugging and found that it works with the limit at around 400. At 500, however, it is off - it should be 21536, but is 21499
EDIT 2: Ah, I found two errors and those seem to have fixed the problem.
The first was found by others who answered, and is that n is overflowing - upon being made a long long data type, it has begun working.
The second, rather facepalm-worthy mistake, was that the booleans in r had to be initialized. After running loop before checking for primes to make all of them false, the right answer is gotten. Does anyone know why this occured?
You simply get an integer overflow. The C++ type int is has a limited range (on a 32 bit System usually from -(2^32) / 2 to 2^32 / 2 - 1, that is the usual maximum is 2147483647 (The specific maximum on your setup can be found out by #including the <limits> header and evaluating std::numeric_limits<int>::max(). Even when k is smaller than the maximum, your code will sooner or later cause an overflow in the expressions n += i + 2 or int j = 2 * i + 2.
You will have to choose a better (read: more appropriate) type like unsigned which does not support negative numbers and can thus can represent numbers twice as large as int. You can also try unsigned long or even unsigned long long.
Also note that variable length arrays (VLAs; that's what bool r[k - 2] is) are not standard C++. You might want to use std::vector instead. You also did not initialize the array to false (std::vector would do this automatically), which could also be the problem, especially if you say that it does not work even at k=500.
In C++, you should also use <ctime> instead of <time.h> (then clock_t and andclock()are defined in thestdnamespace, but since you areusing namespace std`, this won't make a difference for you), but this is more or less a matter of style.
I found a working example in my "code archive". Although it is not based on yours, you might find it useful:
#include <vector>
#include <iostream>
int main()
{
typedef std::vector<bool> marked_t;
typedef marked_t::size_type number_t; // The type used for indexing marked_t.
const number_t max = 500;
static const number_t iDif = 2; // Account for the numbers 1 and 2.
marked_t marked(max - iDif);
number_t i = iDif;
while (i*i <= max) {
while (marked[i - iDif] == true)
++i;
for (number_t fac = iDif; i * fac < max; ++fac)
marked[i * fac - iDif] = true;
++i;
}
for (marked_t::size_type i = 0; i < marked.size(); ++i) {
if (!marked[i])
std::cout << i + iDif << ',';
}
}

Return the result of sum of character arrays

Recently in an interview i was asked a question to write a function which takes two character arrays(integers) as input and returns the output character array.
Function Signature:
char* find_sum(char* a, char* b)
How would one approach this?
Example scenario:
find_sum("12345","32142") = "44487"
Note:
The number of digits can be many(1-100).
u can add huge numbers using the char array approach. however you need to delete the char* after using it every time or use some smart pointer.
char* find_sum(char* a, char* b) {
int lenA = strlen(a), lenB = strlen(b);
int max = lenA > lenB ? lenA : lenB; // Get the max for allocation
char* res = (char*)malloc (max+2);
memset(res, '0', max +1); // set the result to all zeros
res[max+1] = '\0';
int i=lenA - 1, j = lenB - 1, k = max;
for (; i >= 0 || j >=0; --i, --j, --k) {
int sum = 0;
if (i >= 0 && j>=0)
sum = a[i] - '0' + b[j] - '0' + res[k] - '0' ; // add using carry
else if (j >= 0)
sum = b[j] - '0' + res[k] - '0' ; // add the carry with remaining
else if (i >= 0)
sum = a[i] - '0' + res[k] - '0' ;
res[k] = sum % 10 + '0';
res[k-1] = sum / 10 + '0';
}
return res;
}
int main() {
printf (" sum = %s ", find_sum("12345432409240242342342342234234234", "9934563424242424242423442424234"));
return 0;
}
Note: The precondition for the function is the input char arrays should contain only numbers.
The most obvious answer is internally to use something like atoi and sprintf to convert the numbers to integers, do the sum and return the response as a char* However the important thing here is not what the interviewer is asking but why.
In my experience, the interviewer is probably not wanting you to write a hum-dinger of a solution that covers all angles. What they most likely want to get to is what the most common approach would be, and what are the likely limitations of such a function. I.e.:
What happens if your input numbers aren't integers? (e.g. 13.245, 2.3E+7)
What happens if your 'numbers' aren't numbers at all?
What happens if your input integers are really big? (i.e. ~2^31)
How could you detect an error and how would you report it.
How would you allocate memory for the resultant string?
What would the memory allocation imply for the calling code?
What is the efficiency of the function and how could you make it more efficient?
In this way, the interviewer wants to probe your experience of critiquing approaches to problem solving. Naturally, there are many ways of solving this problem. Some of the approaches have side-effects but in certain contexts, these side effects (i.e. integer overflow) may not be greatly important.
Coding is often a trade off between a comprehensive solution and what can be produced quickly (and therefore less expensively) These questions allow the interviewer to get a feel for your understanding of quality - that is, can you design something that is fit for purpose, robust and yet does not take too long to put together - and also your experience of having to identify / resolve common bugs.
You did not mention anything about not using any external command.
We can do this easily on machines that have the bc command. You can add any number of digits:
$ echo "99999999999999999999999999999999+1" | bc
100000000000000000000000000000000
$
We call this bc from the C program. We need to construct the right command line as
echo "n1+n2" | bc
and then use popen to read its result. Below is the function to do that. The code lacks many error checking.
char* find_sum(char* a, char* b) {
int l1 = strlen(a),l2 = strlen(b);
int cmdLen = l1 + l2 + 30; // 30 to accomodate echo,bc and stuff.
char *cmd = malloc(cmdLen);
snprintf(cmd,cmdLen,"echo \"%s+%s\"|bc",a,b);
FILE *fp = popen(cmd, "r");
int max = (l1 > l2) ? l1:l2;
max += 2; // one for additional digit, one for null.
char *result = malloc(max);
fgets(result, max, fp);
return result;
}
Working link
The answer is probably that you have to ask what is returned? Is this a memory allocated string that should be freed by the user or is this a static memory location that is overwritten the next time the function is called?
char* find_sum(char* a, char* b) {
static char buf[MAX_STRING];
...
return buf;
}
or
char* find_sum(char* a, char* b) {
char *buf = malloc(MAX_STRING*sizeof(char));
...
return buf;
}
Giving this answer shows the interviewer that you know more about C than just making an algorithm. (As a side-node: It also shows why a language like java shines in these situations as the garbage collections takes care of freeing the buffer).
Just remember how you did addition in the second grade on the paper.
#include <stdio.h>
#include <string.h>
char *sum(char *a,char *b);
int main()
{
char a[] = "100";
char b[] = "300";
char *c;
c = sum(a,b);
printf("%s",c);
}
char *sum(char *a,char *b)
{
int x,y,z,z2,zLen;
char *result;
x = atoi(a);
y = atoi(b);
z = x + y;
z2 = z;
/* Determine the length of the string now! */
for(zLen = 1; z > 0 || z < 0; zLen++)
z/=10;
result = (char *)malloc(zLen*sizeof(char)+1);
sprintf(result,"%d\0",z2);
return result;
}
Quick and dirty implimentation. Note that I'm not freeing the memory, which is not "ideal". Will fetch you extra brownie points for mentioning that there are no error checks happening here, and no freeing of memory, which is far from ideal in practical situations.
Online Version of Code
Several of the answers mention the use of atoi & itoa functions.
atoi returns int. Your numbers may not fit into an integer data type.
You may try to alleviate the problem (not completely though) using atol, which return a long int, or atoll, which returns a long long int.
Also, itoa is not a standard library function, and hence may not be available on all systems.
Here's another approach. Nothe that I don't like the prototype for find_sum. I'd very much prefer it to be
char *find_sum(char *dst, size_t len, const char *a, const char *b);
letting the caller be responsible for managing resources.
a and b are strings composed of 1 or more digits (and digits only); the result should be freed by caller. Calling find_sum with invalid inputs causes UB :-)
char *find_sum(char *a, char *b) {
char *res;
int alen, blen, rlen;
int carry;
alen = strlen(a);
blen = strlen(b);
rlen = 1 + ((alen > blen) ? alen : blen);
res = malloc(1 + rlen);
if (res) {
int oldlen = rlen;
res[rlen] = 0;
carry = 0;
while (rlen) {
int tmp;
if (alen && blen) tmp = a[--alen] - '0' + b[--blen] - '0';
else if (alen) tmp = a[--alen] - '0';
else if (blen) tmp = b[--blen] - '0';
else tmp = 0;
tmp += carry;
res[--rlen] = '0' + tmp % 10;
carry = tmp / 10;
}
if (res[0] == '0') memmove(res, res+1, oldlen);
}
return res;
}
There's a working version of the function at ideone ( http://ideone.com/O2jrx ).
itoa(atoi(a) + atoi(b), t, 10); if you want to be lazy, where t is a char[MAX_NUMBER_OF_DIGITS].
The real question regards the output array, as mentioned by other users.

C++ BigInt multiplication conceptual problem

I'm building a small BigInt library in C++ for use in my programming language.
The structure is like the following:
short digits[ 1000 ];
int len;
I have a function that converts a string into a bigint by splitting it up into single chars and putting them into digits.
The numbers in digits are all reversed, so the number 123 would look like the following:
digits[0]=3 digits[1]=3 digits[2]=1
I have already managed to code the adding function, which works perfectly.
It works somewhat like this:
overflow = 0
for i ++ until length of both numbers exceeded:
add numberA[ i ] to numberB[ i ]
add overflow to the result
set overflow to 0
if the result is bigger than 10:
substract 10 from the result
overflow = 1
put the result into numberReturn[ i ]
(Overflow is in this case what happens when I add 1 to 9: Substract 10 from 10, add 1 to overflow, overflow gets added to the next digit)
So think of how two numbers are stored, like those:
0 | 1 | 2
---------
A 2 - -
B 0 0 1
The above represents the digits of the bigints 2 (A) and 100 (B).
- means uninitialized digits, they aren't accessed.
So adding the above number works fine: start at 0, add 2 + 0, go to 1, add 0, go to 2, add 1
But:
When I want to do multiplication with the above structure, my program ends up doing the following:
Start at 0, multiply 2 with 0 (eek), go to 1, ...
So it is obvious that, for multiplication, I have to get an order like this:
0 | 1 | 2
---------
A - - 2
B 0 0 1
Then, everything would be clear: Start at 0, multiply 0 with 0, go to 1, multiply 0 with 0, go to 2, multiply 1 with 2
How can I manage to get digits into the correct form for multiplication?
I don't want to do any array moving/flipping - I need performance!
Why are you using short to store digits in the [0..9] a char would suffice
You're thinking incorrectly about the multiplication. In the case of multiplication you need a double for loop that multiplies B with each digit in A and sums them up shifted with the correct power of ten.
EDIT: Since some anonymous downvoted this without a comment this is basically the multiplication algorithm:
bigint prod = 0
for i in A
prod += B * A[i] * (10 ^ i)
The multiplication of B with A[i] is done by an extra for loop where you also keep track of the carry. The (10 ^ i) is achieved by offseting the destination indices since bigint is in base 10.
Your example in the question is over-engineering at its best in my opinion. Your approach will end up even slower than normal long multiplication, because of the shear number of multiplications and additions involved. Don't limit yourself to working at one base digit at a time when you can multiply approximately 9 at a time!. Convert the base10 string to a hugeval, and then do operations on it. Don't do operations directly on the string. You will go crazy. Here is some code which demonstrates addition and multiplication. Change M to use a bigger type. You could also use std::vector, but then you miss out on some optimizations.
#include <iostream>
#include <string>
#include <algorithm>
#include <sstream>
#include <cstdlib>
#include <cstdio>
#include <iomanip>
#ifdef _DEBUG
#include <assert.h>
#define ASSERT(x) assert(x)
#else
#define ASSERT(x)
#endif
namespace Arithmetic
{
const int M = 64;
const int B = (M-1)*32;
struct Flags
{
Flags() : C(false),Z(false),V(false),N(false){}
void Clear()
{
C = false;
Z = false;
V = false;
N = false;
}
bool C,Z,V,N;
};
static unsigned int hvAdd(unsigned int a, unsigned int b, Flags& f)
{
unsigned int c;
f.Clear();
//b = -(signed)b;
c = a + b;
f.N = (c >> 31UL) & 0x1;
f.C = (c < a) && (c < b);
f.Z = !c;
f.V = (((signed)a < (signed)b) != f.N);
return c;
}
static unsigned int hvSub(unsigned int a, unsigned int b, Flags& f)
{
unsigned int c;
f.Clear();
c = a - b;
//f.N = ((signed)c < 0);
f.N = (c >> 31UL) & 0x1;
f.C = (c < a) && (c < b);
f.Z = !c;
f.V = (((signed)a < (signed)b) != f.N);
return c;
}
struct HugeVal
{
HugeVal()
{
std::fill(part, part + M, 0);
}
HugeVal(const HugeVal& h)
{
std::copy(h.part, h.part + M, part);
}
HugeVal(const std::string& str)
{
Flags f;
unsigned int tmp = 0;
std::fill(part, part + M, 0);
for(unsigned int i=0; i < str.length(); ++i){
unsigned int digit = (unsigned int)str[i] - 48UL;
unsigned int carry_last = 0;
unsigned int carry_next = 0;
for(int i=0; i<M; ++i){
tmp = part[i]; //the value *before* the carry add
part[i] = hvAdd(part[i], carry_last, f);
carry_last = 0;
if(f.C)
++carry_last;
for(int j=1; j<10; ++j){
part[i] = hvAdd(part[i], tmp, f);
if(f.C)
++carry_last;
}
}
part[0] = hvAdd(part[0], digit, f);
int index = 1;
while(f.C && index < M){
part[index] = hvAdd(part[index], 1, f);
++index;
}
}
}
/*
HugeVal operator= (const HugeVal& h)
{
*this = HugeVal(h);
}
*/
HugeVal operator+ (const HugeVal& h) const
{
HugeVal tmp;
Flags f;
int index = 0;
unsigned int carry_last = 0;
for(int j=0; j<M; ++j){
if(carry_last){
tmp.part[j] = hvAdd(tmp.part[j], carry_last, f);
carry_last = 0;
}
tmp.part[j] = hvAdd(tmp.part[j], part[j], f);
if(f.C)
++carry_last;
tmp.part[j] = hvAdd(tmp.part[j], h.part[j], f);
if(f.C)
++carry_last;
}
return tmp;
}
HugeVal operator* (const HugeVal& h) const
{
HugeVal tmp;
for(int j=0; j<M; ++j){
unsigned int carry_next = 0;
for(int i=0;i<M; ++i){
Flags f;
unsigned int accum1 = 0;
unsigned int accum2 = 0;
unsigned int accum3 = 0;
unsigned int accum4 = 0;
/* Split into 16-bit values */
unsigned int j_LO = part[j]&0xFFFF;
unsigned int j_HI = part[j]>>16;
unsigned int i_LO = h.part[i]&0xFFFF;
unsigned int i_HI = h.part[i]>>16;
size_t index = i+j;
size_t index2 = index+1;
/* These multiplications are safe now. Can't overflow */
accum1 = j_LO * i_LO;
accum2 = j_LO * i_HI;
accum3 = j_HI * i_LO;
accum4 = j_HI * i_HI;
if(carry_next){ //carry from last iteration
accum1 = hvAdd(accum1, carry_next, f); //add to LSB
carry_next = 0;
if(f.C) //LSB produced carry
++carry_next;
}
/* Add the lower 16-bit parts of accum2 and accum3 to accum1 */
accum1 = hvAdd(accum1, (accum2 << 16), f);
if(f.C)
++carry_next;
accum1 = hvAdd(accum1, (accum3 << 16), f);
if(f.C)
++carry_next;
if(carry_next){ //carry from LSB
accum4 = hvAdd(accum4, carry_next, f); //add to MSB
carry_next = 0;
ASSERT(f.C == false);
}
/* Add the higher 16-bit parts of accum2 and accum3 to accum4 */
/* Can't overflow */
accum4 = hvAdd(accum4, (accum2 >> 16), f);
ASSERT(f.C == false);
accum4 = hvAdd(accum4, (accum3 >> 16), f);
ASSERT(f.C == false);
if(index < M){
tmp.part[index] = hvAdd(tmp.part[index], accum1, f);
if(f.C)
++carry_next;
}
carry_next += accum4;
}
}
return tmp;
}
void Print() const
{
for(int i=(M-1); i>=0; --i){
printf("%.8X", part[i]);
}
printf("\n");
}
unsigned int part[M];
};
}
int main(int argc, char* argv[])
{
std::string a1("273847238974823947823941");
std::string a2("324230432432895745949");
Arithmetic::HugeVal a = a1;
Arithmetic::HugeVal b = a2;
Arithmetic::HugeVal d = a + b;
Arithmetic::HugeVal e = a * b;
a.Print();
b.Print();
d.Print();
e.Print();
system("pause");
}
Andreas is right, that you have to multiply one number by each digit of the other and sum the results accordingly. It is better to multiply a longer number by digits of the shorter one I think. If You store decimal digits in Your array char would indeed suffice, but if you want performance, maybe you should consider bigger type. I don't know what Your platform is, but in case of x86 for example You can use 32 bit ints and hardware support for giving 64 bit result of 32 bit multiplication.
Alright seeing that this question is answered almost 11 years ago, I figure I'll provide some pointers for the one who is writing their own BigInt library.
First off, if what you want is purely performance instead of studying how to actually write performant code, please just learn how to use GMP or OpenSSL. There is a really really steep learning curve to reach the level of GMP's performance.
Ok, let's get right into it.
Don't use base 10 when you can use a bigger base.
CPUs are god-level good at addition, subtraction, multiplication, and division, so take advantage of them.
Suppose you have two BigInt
a = {9,7,4,2,6,1,6,8} // length 8
b = {3,6,7,2,4,6,7,8} // length 8
// Frustrating writing for-loops to calculate a*b
Don't make them do 50 calculations in base 10 when they could do 1 calculations of base 2^32:
a = {97426168}
b = {36724678}
// Literally only need to type a*b
If the biggest number your computer can represent is 2^64-1, use 2^32-1 as the base for your BigInt, as it will solve the problem of actually overflowing when doing multiplication.
Use a structure that supports dynamic memory. Scaling your program to handle the multiplication of two 1-million digits numbers would probably break you program since it doesn't have enough memory on the stack. Use a std::vector instead of std::array or raw int[] in C to make use of your memory.
Learn about SIMD to give your calculation a boost in performance. Typical loops in noobs' codes can't process multiple data at the same time. Learning this should speed things up from 3 to 12 times.
Learn how to write your own memory allocators. If you use std::vector to store your unsigned integers, chances are, later on, you'll suffer performance problems as std::vector is only for general purposes only. Try to tailor your allocator to your own need to avoid allocating and reallocating every time a calculation is performed.
Learn about your computer's architecture and memory layout. Writing your own assembly code to fit certain CPU architecture would certainly boost your performance. This helps with writing your own memory allocator and SIMD too.
Algorithms. For small BigInt you can rely on your grade school multiplication but as the input grows, certainly take a good look at Karatsuba, Toom-Cook, and finally FFT to implement in your library.
If you're stuck, please visit my BigInt library. It doesn't have custom allocator, SIMD code or custom assembly code, but for starters of BigInteger it should be enough.
I'm building a small BigInt library in C++ for use in my programming language.
Why? There are some excellent existing bigint libraries out there (e.g., gmp, tommath) that you can just use without having to write your own from scratch. Making your own is a lot of work, and the result is unlikely to be as good in performance terms. (In particular, writing fast code to perform multiplies and divides is quite a lot trickier than it appears at first glance.)