I have written this code to calculate 2^n mod 10^9+7. But sadly this function works only till 2^31 and afterwards all the answers are zero.
Can somebody shed some light why?
typedef unsigned long long LL;
const int MOD = 1000000007;
LL powmod(int a,int n)
{
LL p=1;
for(;n;)
{
if(n%2) p=(p*a)%MOD;
if(n/=2) a=(a*a)%MOD;
}
return p;
}
Just change LL powmod(int a,int n) to LL powmod(LL a,int n).
As squeamish ossifrage hinted at, with int a, the subexpression a*a is computed in int range and overflows "when a * a exceeds MAX_INT" (M.M), while with LL a, it is computed in unsigned long long range.
Related
My code for finding 10th decimal digit of square root of 2.
#include <stdio.h>
unsigned long long int power(int a, int b);
unsigned long long int root(int a);
int main()
{
int n;
n=10;
printf("%llu \n",root(n));
return 0;
}
unsigned long long int power(int a, int b)
{
int i;
unsigned long long int m=1;
for (i=1;i<=b;i++)
{
m*=a;
}
return m;
}
unsigned long long int root(int a)
{
unsigned long long int c=1;
int counter=1;
while(counter<=a)
{
c*=10;
while(power(c,2)<=2*power(10,2*counter))
{
c++;
}
c-=1;
counter++;
}
return c;
}
I have tried the same algorithm in python. It can find the 10th decimal digit of $sqrt{2}$ immediately.
However, while doing C, I have waited for 10 mins but without a result.
Python handles big numbers for you. [1]
Although, as you say that you are getting the answer "immediately", your algorithm in python is not probably the same as the one you used in C.
#bruno's answer already explains why you are not getting the expected results in C.
[1] Handling very large numbers in Python
Exceed the range that the data can represent. when counter is equal to 10,2*power(10,2*counter) exceeds the range that unsigned long long int can represent. Python supports large number calculations, unlimited digits
you have overflow(s)
when counter values 10 you try to compute power(10,20) but even long long on 64 bits are not enough large, so you loop in
while(power(c,2)<=2*power(10,2*counter)){
c++;
}
for a long time (may be without ending)
Having long long on 64 bits allows to compute the result for n valuing up to 9
I have two functions here that together compute the nCr:
int factorial(int n) {
int c;
int result = 1;
for (c = 1; c <= n; c++)
{
result = result*c;
}
return result;
}
int nCr(int n, int r) {
int result;
result = factorial(n)/(factorial(r)*factorial(n-r));
return result;
}
I am having trouble with an error check I need to implement. As n gets larger, I won't have the ability to computer n! and this error check has to exist in both nCr and factorial. They both must detect this overflow.
Currently, when I enter a number that is too large for computation, I get a floating type error returned from the command line.
I am having trouble accounting for this overflow check. Any help would be much appreciated, thanks.
A better way of calculating binomial coefficients
typedef unsigned long long ull;
ull nCr(int n, int r) {
ull res = 1;
if (r > n - r) r = n - r;
for (int i = 0; i < r; ++i) {
res *= (n - i);
res /= (i + 1);
}
return res;
}
In your code, the maximum value is always factorial(n),
so you only need to check that n! isn't bigger than 2.147.483.647 (max int value).
Please note that the stored max value can be different based on the size of the int type in memory (different machines can specify different sizes).
However, the last bit in int type variables is reserved for storing the sign (+ or -), thus the max value can be half of 65.535 and 4.294.967.295 i.e. 32.767 and 2.147.483.647 for int types.
SIZE_OF_INT(bits) MAX VALUE(UNSIGNED) MAX_VALUE(SIGNED)
---------------------------------------------------------------
16 65.535 32.767
32 4.294.967.295 2.147.483.647
The value of 13! can go beyond the max value of the int type (in 32 bit).
12! = 479.001.600 and
13! = 6.227.020.800
So, you need to check in nCr(int n, int r) that the max value of n is always less than 13 (i.e. n<=12) and r<=n.
And in factorial(int n): n<=12.
I don't understand why this code compiles and then segfaults:
#include <stdio.h>
#include <stdlib.h>
unsigned long int gcd(unsigned long int, unsigned long int);
unsigned long int lcm(unsigned long int, unsigned long int);
int main(int argc, char *argv[]) {
int i;
unsigned long int n = 1L;
for (i = 2; i < 21; i++) {
n = lcm(n, i);
}
printf("%ld\n", n);
return 0;
}
unsigned long int gcd(unsigned long int a, unsigned long int b) {
if (a == b) return a;
if (a > b) return gcd(a - b, b);
return gcd(a, b - a);
}
unsigned long int lcm(unsigned long int a, unsigned long int b) {
return abs(a * b) / gcd(a, b);
}
Are those unsigned longs even necessary? I also noted that if I change that 21 to a 18 it gives the correct result. The code is meant to find the LCM of all the numbers from 1 to 20.
Running it in gdb gives:
Program received signal SIGSEGV, Segmentation fault.
0x0000000000400643 in gcd (a=7536618, b=18) at p5.c:19
19 if (a > b) return gcd(a - b, b);
You're overflowing the stack. Which is a shame, because that should be easily optimized as tail recursion, full recursion is extremely overkill for this. Using the proper optimization levels in any modern compiler (cl, gcc, icc) should get rid of the segfault.
Luckily writing this iteratively is trivial as hell:
unsigned long gcd(unsigned long a, unsigned long b)
{
while(a != b)
if(a > b)
a -= b;
else
b -= a;
return a;
}
Due to how the stack and how they work, there's a limit on how deep function calls can be nested, depending on how much local state they keep.
For extremely imbalanced arguments, implementing gcd by repeated subtraction requires a lot of iterations, and so your recursion goes way to deep. You need to either change the implementation (e.g. make it iterative), or change the algorithm (e.g. compute remainders instead of differences).
You could increase the stack size, but that is wasteful of memory and the larger size will run eventually run out too with larger inputs.
I write a algorithm to get the sum of float points number, and this algorithm works perfect for integer but when I applied to float points, the sum I got is a negative number. however my array of float points does only have positive float points number. here I post my code, thank you for checking it.
static unsigned int do_heap_sum(double ary[], unsigned int n,
double *result)
{
unsigned int j;
int counter=0;
double sum=0;
double min;
while(n>counter){
make_heap(ary,n);
min=ary[0];
sum=sum+min;
for(j=1;j<n;j++){
ary[j-1]=ary[j];
}
counter=counter+1;
}
*result=sum;
//exit(EXIT_FAILURE);
return 0;
}
in this code, I use the make_heap to find the min. do you think this has problem? (this make_heap works perfectly with integers extracting the min of array).
thanks again.
In your code, you want to calculate sum of the heap which stored in double[], so make_heap is superfluous, a simple loop is enough.
Make sure double is big enough to save the sum.
For ary[j-1] = ary[j] in for(j=1;j<n;j++), why not just swap ary[0] and ary[n - counter - 1] then adjust the heap in next loop, it's much cheaper.
My wild guess is that you used an integer version of make_heap:
void make_heap(int *ary,size_t n);
instead of a double precision float version:
void make_double_heap(double *ary,size_t n);
Otherwise, I notice that you sort a heap of size n, n times: that's too much work. What happens when some elements of ary are duplicated ?
You could rewrite the loop:
static unsigned int do_heap_sum(double ary[], unsigned int n,
double *result)
{
unsigned int counter=0;
double sum=0;
double min;
while(n>counter){
make_double_heap(ary+counter,n-counter);
min=ary[counter];
sum=sum+min;
counter=counter+1;
}
*result=sum;
return 0;
}
I am trying to compute n! % m using recursion in C. This is the code I am using
#include<stdio.h>
#define m 1000000007
long long int fact(long long int n) {
if(n == 1)
return (1);
long long int n2 = (long long int)(fact(n-1));
long long int k = (n*n2)%m;
return k;
}
int main() {
printf("%lld",fact(1000000));
}
This program gives SEGMENTATION FAULT , but if I replace the fact function with an iterative approach then program prints correct answer.The iterative fact function is
long long int fact(long long int n){
long long int k =1;
long long int i;
for(i = n;i>1;i--)
k = (k*i)%m;
return k;
}
So why the iterative approach works but the recursive approach is failing?
try gdb, but likely its because you are reaching your max recursion depth, in other words running out of "memory" either literally or based on current rule sets for your os.
If your C compiler optimizes tail calls you can rewrite your recursive function to a tail recursive one:
long long int fact_aux(long long int n, long long int acc) {
if(n <= 1)
return acc;
return fact_aux(n-1, (n * acc)%m);
}
long long int fact(long long int n) {
return fact_aux(n, 1);
}
Note that the C standard doesn't require TCO so you have no guarantee this will be as effective as a loop. GCC does it.