This is also a math related question, but I'd like to implement it in C++...so, I have a number in the form 2^n
, and I have to calculate the sum of its digits ( in base 10;P ). My idea is to calculate it with the following formula:
sum = (2^n mod 10) + (floor(2^n/10) mod 10) + (floor(2^n/100) mod 10) + ...
for all of its digits: floor(n/floor(log2(10)))
.
The first term is easy to calculate with modular exponentiation, but I'm in trouble with the others.
Since n
is big, and I don't want to use my big integer library, I can't calculate pow(2,n)
without modulo. A code snippet for the first term:
while (n--){
temp = (temp << 1) % 10;
};
but for the second I have no idea. I also cannot floor
them individually, since it would give '0' (2/10). Is it possible to achieve this?
(http://www.mathblog.dk/project-euler-16/ for the easier solution.) Of course I will look for other way if it cannot be done with this method. (for example storing digits in byte array, as in the comment in the link).
Edit: Thanks for the existing answers, but I look for some way to solve it mathematically. I've just came up with one idea, which can be implemented without bignum or digit-vectors, I'm gonna test if it works.
So, I have the equation above for the sum. But 2^n/10^k
can be written as 2^n/2^(log2 10^k)
which is 2^(n-k*log2 10)
. Then I take it's fractional part, and its integer part, and do modular exponentiation on the integer part: 2^(n-k*log2 10) = 2^(floor(n-k*log2 10)) * 2^(fract(n-k*log2 10))
. After the last iteration I also multiply it with the fractional modulo 10. If it won't work or if I'm wrong somewhere in the above idea, I stick to the vector solution and accept an answer.
Edit: Ok, it seems doing modular exponentiation with non-integer modulo is not possible(?) (or I haven't found anything about it). So, I'm doing the digit/vector based solution.
The code does NOT work fully!
It does not give the good value: (1390 instead of 1366):
typedef long double ldb;
ldb mod(ldb x, ldb y){ //accepts doubles
ldb c(0);
ldb tempx(x);
while (tempx > y){
tempx -= y;
c++;
};
return (x - c*y);
};
int sumofdigs(unsigned short exp2){
int s = 0;
int nd = floor((exp2) * (log10(2.0))) + 1;
int c = 0;
while (true){
ldb temp = 1.0;
int expInt = floor(exp2 - c * log2((ldb)10.0));
ldb expFrac = exp2 - c * log2((ldb)10.0) - expInt;
while (expInt>0){
temp = mod(temp * 2.0, 10.0 / pow(2.0, expFrac)); //modulo with non integer b:
//floor(a*b) mod m = (floor(a mod (m/b)) * b) mod m, but can't code it
expInt--;
};
ldb r = pow(2.0, expFrac);
temp = (temp * r);
temp = mod(temp,10.0);
s += floor(temp);
c++;
if (c == nd) break;
};
return s;
};