Function to find sum of digits in the number a^b where a, b are positive integers I was solving Project Euler problem 16, which asks to find the sum of digits of the number 2 raised to the power 1000. Using Python, it can be solved in one line of code:

sum(map(int, list(str(2**1000))))


It felt too easy so I decided to write a function in C to do the same job. Here's my program. In what ways can I improve it?  Please suggest good practices also.

#include &lt;stdio.h&gt;
#include &lt;stdlib.h&gt;
#include &lt;math.h&gt;
#include &lt;assert.h&gt;

int sumdigit(int a, int b);

int main(void) {
    int a = 2;
    int b = 10000;
    printf("%d\n", sumdigit(a, b));
    return 0;
}

int sumdigit(int a, int b) {
    // numlen = number of digit in a^b
    // pcount = power of 'a' after ith iteration
    // dcount = number of digit in a^(pcount)

    int numlen = (int) (b * log10(a)) + 1;
    char *arr = calloc(numlen, sizeof *arr);
    int pcount = 0;
    int dcount = 1;
    arr[numlen - 1] = 1;
    int i, sum, carry;

    while(pcount &lt; b) {
        pcount += 1;

        sum = 0; 
        carry = 0;

        for(i = numlen - 1; i &gt;= numlen - dcount; --i) {
            sum = arr[i] * a + carry;
            carry = sum / 10;
            arr[i] = sum % 10;
        }

        while(carry &gt; 0) {
            dcount += 1;
            sum = arr[numlen - dcount] + carry;
            carry = sum / 10;
            arr[numlen - dcount] = sum % 10;
        } 
    }

    int result = 0;
    for(i = numlen - dcount; i &lt; numlen; ++i)
        result += arr[i];

    free(arr);
    return result;
}
The problem calls for computing the sum of digits in 21000.  You did 210000.  Overachiever!

There are a few things you could do to improve readability.

char *arr looks a lot like a string.  One might initially think that you are storing the number as a string (i.e., ASCII '0'… '9').  You could dispel that impression by changing it to unsigned char *arr.  To be even clearer, I would use a typedef unsigned char digit; so that you can declare digit *arr.  Then it is clear that you are using binary-coded decimal.

As long as you are doing binary-coded decimal, there is no advantage to putting the most-significant digit first.  With the least-significant digit first, the code is simpler, and there is the nice property that the number is sum(arr[i] * 10**i for i in range(len(arr))).

For further readability, I would define a struct to represent the big decimal:

typedef unsigned char digit;

typedef struct {
    int capacity;
    int dcount;
    digit *digits;  /* Unsigned binary-coded decimal. The number is
                       sum(arr[i] * 10**i for i in range(dcount)) */
} bigdecimal;


There are a lot of variables in your sumdigit() — not quite a mess, but enough to start being concerned.  The function name sumdigit is also a bad code smell.  I would also decompose the operations for readability.  (Defining the bigdecimal type makes that practical.)

void mult(unsigned int a, bigdecimal *b) {
    int carry = 0;

    for (int i = 0; i &lt; b-&gt;dcount; ++i) {
        int sum = a * b-&gt;digits[i] + carry;
        carry = sum / 10;
        b-&gt;digits[i] = sum % 10;
    }

    while (carry &gt; 0) {
        int sum = b-&gt;digits[b-&gt;dcount] + carry;
        carry = sum / 10;
        b-&gt;digits[b-&gt;dcount] = sum % 10;
        b-&gt;dcount++;
    }
}

bigdecimal *exponentiate(unsigned int base, unsigned int power) {
    bigdecimal *result = malloc(sizeof(bigdecimal));
    result-&gt;capacity = 1 + (int) (power * log10(base));
    result-&gt;digits = calloc(result-&gt;capacity, sizeof(digit));

    /* base**0 == 1 */
    result-&gt;digits[0] = 1;
    result-&gt;dcount = 1;

    for (int p = 0; p &lt; power; p++) {
        mult(base, result);
    }

    return result;
}

unsigned int sumdigit(bigdecimal *b) {
    unsigned int sum = 0;
    for (int i = b-&gt;dcount - 1; i &gt;= 0; --i) {
        sum += b-&gt;digits[i];
    }
    return sum;
}

void free_bigdecimal(bigdecimal *b) {
    free(b-&gt;digits);
    free(b);
}

int main(void) {
    bigdecimal *n = exponentiate(2, 1000);
    printf("%u\n", sumdigit(n));
    free_bigdecimal(n);
    return 0;
}


I've used C99 variable scoping in the for-loops because it's nicer.