c++ - Small error when taking modulo -


i've written little algorithm calculates series of numbers, big store in unsigned long long. why i've decided take modulo every time next number calculated. function:

#define mod 1000000007  template <typename t> t modpow(t base, t exp, t modulus) {     base %= modulus;     t result = 1;     while (exp > 0) {         if (exp & 1) result = (result * base) % modulus;         base = (base * base) % modulus;         exp >>= 1;     }     return result; }  vector<unsigned long long> b(int n) {     vector<unsigned long long> points;     vector<unsigned long long> cum_points;      points.push_back(0);     points.push_back(0);      cum_points = points;      unsigned long long prev = 0;     if (n >= 2){         (int = 0; <= n - 2; i++) {             prev += cum_points[i];             prev %= mod;             points.push_back((modpow((unsigned long long)2, (unsigned long long)i, (unsigned long long) mod)+prev)%mod);             cum_points.push_back((cum_points[i+1]+points[i+2])%mod);         }     }     return points; } 

this returns vector series of numbers:

0, 0, 1, 2, 5, 12, 28, 64, 144, 320, 704, 1536, 3328, ...

and on...

the problem when n > 50 modulo off: (the first values ones calculated without modulo in code, , values after equal signs results modulo in code.)

50: 1759218604441600 % 1000000007 = 592127074; right answer 51: 3588805953060860 % 1000000007 = 927939229; should be: 927939225 

the error gets bit larger every time n gets higher. little offset come from?

some possible problems:

  • the modpow() somehow doesn't give right answer when numbers exceed length. this not problem
  • there mistake made math, believe used following equations right way:

(a*b) mod c = ((a mod c)*(b mod c)) mod c

(a + b) mod c = ((a mod c)+(b mod c)) mod c

  • i have wrong variable type in code, although wouldn't know where.

edit: i've ruled out of possible problems , problem seems lie within calculation of prev when i == 48.

you check whether modulus small enough. have checked size of unsigned long long on system?

std::cout << std::numeric_limits<unsigned long long>::max(); 

when check that, might check size of unsigned int @ same time. i'm not sure different.

your modulus has 10 digits, product of 2 numbers have 20 digits. if max unsigned long long smaller mod * mod, getting overflow error.

an error in formula show before n = 51.

comments: if using c++11 standard, why not replace macro with

constexpr unsigned long long mod = 1000000007; 

also, in spot call modpow, avoid casts unsigned long long calling specific function want: modpow<unsigned long long>. arguments converted right type automatically.