C: Convert string to number when the value is arbitrarily large - c

As far as I can tell, in C all the numeric types have a fixed upper limit. Therefore, to convert a string to a number, you have to know how big the number could possibly be.
Is there any way to convert strings to numbers without placing any kind of limit on the size of the numbers? In case it matters, the numbers I care about are negative.

The core C language only supports integers of a definite size. The stock facility for converting decimal (text) numbers to binary (machine) numbers is the strto* family of functions1 and, as you have probably already noticed, they require you to choose an appropriately-sized integer type for the input you expect. Normally, when programming in C, it's possible to say that your program only needs to be able to support numbers in some fixed range, and just raise an error if you receive input outside that range.
If you truly need to support arbitrarily large2 numbers, then you need an add-on library. The general terms for these libraries are "bignum", "multiple precision arithmetic", and "arbitrary precision arithmetic". One well-written, freely-licensed bignum library is GNU MP.
1 The related ato* and *scanf functions are broken as designed - never use them for anything. One of the ways they are broken is that they make it impossible to tell when you've received input outside the supported range.
2 in absolute value, i.e. arbitrarily far away from zero in either direction

here's my attempt , I'm working with a maximum of 64bit int (but you can change the type to whatever it is that you like) with 8 offset , meaning if you surpass 8bit (ex. 257), it'll output 16 bits , if you surpass 16 bits it'll output 24bits ... etc, I also used the first bit as the sign bit 1 for negative and 0 for positive;
#include <stdio.h>
#include <stdlib.h>
#include <sys/types.h>
#include <math.h>
void btd(int64_t num , char* res);
int act_size(int64_t num);
int main(void)
{
char res[64];
btd(-200 , res);
printf("%s\n" , res);
}
void btd(int64_t num , char* res)
{
int64_t tmp;
int neg = 0;
int size = 0;
int64_t one_check;
int i;
if(num < 0)
neg++;
if(num < 0)
tmp = num * -1;
else
tmp = num;
size = act_size(tmp);
one_check = pow(2 , size - 1);
printf("size %d\none flag : %ld\n" , size , one_check);
for( i = 0 ; i < size + 1; i++)
{
if(!i)
{
if(neg)
{
neg = 0;
res[0] = '1';
num <<= 1;
}
else
{
res[0] = '0';
num <<= 1;
}
continue;
}
if(tmp & one_check)
{
res[i] = '1';
tmp <<= 1;
}
else
{
res[i] = '0';
tmp <<= 1;
}
}
res[i] = '\0';
}
int act_size(int64_t ar)
{
int count = 1;
int last_one;
int size;
int64_t num = ar;
if(num < 0)
num *= -1;
while(num)
{
printf("NUM : %ld\n" , num);
if(num & 1)
{
last_one = count;
num >>= 1;
}
else
num >>=1;
count++;
}
printf("NUM : %ld\nLAST : %d\n" , num , last_one);
if(last_one <= 8)
return 8;
else if (last_one <= 16)
return 16;
else if (last_one <= 24)
return 24;
else if (last_one <= 32)
return 32;
else if (last_one <= 40)
return 40;
else if (last_one <= 48)
return 48;
else if (last_one <= 56)
return 56;
else
return 64;
}
the output of this will be (since we gave it -200 as an argument)
NUM : 200
NUM : 100
NUM : 50
NUM : 25
NUM : 12
NUM : 6
NUM : 3
NUM : 1
NUM : 0
LAST : 8
size 8
one flag : 128
111001000

Related

Print an integer digit by digit

I have a function print_number.
The function checks if in front of the number there exists '-', then it reverse the number and takes every digit and prints it. The algorithm works pretty good but if i give -2.147.483.648 ( which should be the bottom limit of an integer ) it pritns -0 and i don't know why.
#include<stdio.h>
void print_char(char character)
{
printf("%c",character);
}
void print_number(int nr)
{
int reverse=0;
if (nr < 0)
{
print_char('-');
nr *= -1;
}
while(nr > 9)
{
reverse = reverse * 10 + nr % 10;
nr = nr / 10;
}
print_char(nr + '0');
while(reverse)
{
print_char(reverse % 10 + '0');
reverse = reverse / 10;
}
}
When you are doing
if (nr < 0)
{
print_char('-');
nr *= -1;
}
It inverses negative number to the positive one.
If you will run it for -2.147.483.648, you will receive
nr = 2.147.483.648 // == binary 1 0000000000000000000000000000000
As INT is 32 BIT variable in your architecture (and at least 16 BIT variable by the spec), so '1' overflows it and so on
nr = 0 // For gcc-like C realisation
And accepting the ISO9899 spec, this behaviour of signed int overflow is realisation-specified thing and may not be predicted in common.
Use long long value if you're needing to use your program for larger values.
Something like:
#include<stdio.h>
void print_char(char character)
{
printf("%c",character);
}
void print_number(long long nr)
{
int reverse=0;
if (nr < 0)
{
print_char('-');
nr *= -1;
}
while(nr > 9)
{
reverse = reverse * 10 + nr % 10;
nr = nr / 10;
}
print_char(nr + '0');
while(reverse)
{
print_char(reverse % 10 + '0');
reverse = reverse / 10;
}
}
void main(void){
print_number(-2147483648LL);
}
And test:
> gcc test.c
> ./a.out
-2147483648
Firstly, the MAX and MIN range for an INT are -2,147,483,648 and 2,147,483,647 respectively.
Negating -2,147,483,648 means a positive value 2,147,483,648 would result in an overflow by 1 as it is out of bounds for the MAX range.
This operation will result in the same value of -2,147,483,648.
Secondly, you might encounter an overflow during the integer reversing process.
Example, reversing 2147483647 causes an overflow after the intermediate result of 746384741.
Therefore, you should handle that by throwing an exception or returning 0.
Thirdly, your loop for reversing the number is inaccurate. It should loop till while(nr != 0)
Here's the complete code.
#include <stdio.h>
#include <stdlib.h>
#include <stdbool.h>
int main()
{
void reverseNumber(int);
reverseNumber(124249732);
return 0;
}
void reverseNumber(int nr)
{
printf("nr = %d\n", nr);
int reverse = 0;
bool neg = false;
if (nr < 0) {
neg = true;
nr *= -1;
}
while (nr != 0) {
int digit = nr % 10;
int result = reverse * 10 + digit;
if ((result - digit) / 10 != reverse) {
printf("ERROR\n");
exit(0);
}
reverse = result;
nr = nr / 10;
}
if(neg) {
printf("%c", '-');
}
printf("%d\n", reverse);
}
nr *= -1; is a problme when nr == INT_MIN as that is signed integer overflow. The result is undefined behavior (UB). Best to avoid.
Wider integers are not always available.
Using OP's general, approach, do not change the sign of nr until it is reduced.
void print_number(int nr) {
int reverse = 0;
if (nr < 0) {
print_char('-');
//nr *= -1;
}
while (nr/10) { // new test
reverse = reverse * 10 + nr % 10;
nr = nr / 10;
}
reverse = abs(reverse); // reverse = |reverse|
nr = abs(nr); // nr = |nr|
print_char(nr + '0');
while (reverse) {
print_char(reverse % 10 + '0');
reverse = reverse / 10;
}
}

Largest number data type in C

So I wrote a simple C program which displays the nth fibonacci number based on user specification. I started using ints and obviously that did not work out too well so I then went to floats, longs, and finally long longs. Even with long longs there is a cut off to where I get nonsensical or incorrect output such as negative numbers ( starts to happen a bit before n = 100 ). Is there anything I can do to expand the range of this program or is there no way to fix this?
#include <stdio.h>
#include <stdlib.h>
int main()
{
long long term = 0;
long long val = 0;
long long first = 0;
long long second = 1;
printf( "Which fibonacci term (starting at 0) would you like to see? ");
scanf("%lld", &term );
if( term == 0 )
{
printf("%lld\n", first );
return 1;
}
if( term == 1 )
{
printf( "%lld\n", second );
return 1;
}
if( term > 1 )
{
for( int i = 1; term > i; i++ )
{
val = first + second;
first = second;
second = val;
}
printf( "%lld\n", val );
return 1;
}
return 0;
}
As per ISO C99, a long long is 64bit at the minimum - the standard integer data type with the largest size. Your compiler may allow for larger types, and these are defined by intmax_t and uintmax_t in <stdint.h>.
However, I would strongly recommend using a Bigint library such as GMP.
Using GMP, the only limitation for long integers and floating points is the resources available on the system.
Change all of your types to unsigned long long which will perform unsigned arithmetic, nearly doubling the range. If you wish to extend this further you will need to create your own data type. A few examples of libraries that can do this for you:
GMP
OpenSSL BN
Edit per Michael Burr's comment:
Requires your platform to have unsigned long longs that are greater than 64 bits, such as 128 bits (or more). C99 only guarantees that long long is at least 64 bits. The range of your particular program won't change if long long is only 64 bits.
One can use uintmax_t but that is likely <= 128 bits.
GMP is an excellent library to consider.
But one only needs to write an extend precision add() as below. Not very efficient, but it gets the job done for fib(). Here I use a C string as the data type. Other types of your design could work far more better.
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#define max(a, b) ((a) > (b) ? (a) : (b))
// "Add" 2 strings
char *strsum(const char *a, const char *b) {
size_t alen = strlen(a);
size_t blen = strlen(b);
size_t clen = max(alen, blen) + 1;
size_t csize = clen + 1;
char *c = malloc(csize);
if (c == NULL) return NULL;
c[clen] = '\0';
int carry = 0;
while (alen > 0 && blen > 0) {
int sum = a[--alen] - '0' + b[--blen] - '0' + carry;
c[--clen] = sum%10 + '0';
carry = sum / 10;
}
while (alen > 0) {
int sum = a[--alen] - '0' + carry;
c[--clen] = sum%10 + '0';
carry = sum / 10;
}
while (blen > 0) {
int sum = b[--blen] - '0' + carry;
c[--clen] = sum%10 + '0';
carry = sum / 10;
}
if (carry) {
c[--clen] = carry + '0';
}
if (clen > 0) {
memmove(&c[0], &c[1], csize - 1);
}
return c;
}
void fib(unsigned n) {
char *a = NULL;
char *b = malloc(2); strcpy(b, "0");
char *c = malloc(2); strcpy(c, "1");
unsigned i;
for (i=1; i<n; i++) {
free(a);
a = b;
b = c;
c = strsum(a, b);
if (c == NULL) break;
printf("fib(%u) = %s\n", i+1, c);
}
free(a);
free(b);
free(c);
}
int main(int argc, char *argv[]) {
fib(1000);
return 0;
}
Sample
fib(2) = 1
fib(3) = 2
fib(4) = 3
fib(5) = 5
fib(6) = 8
fib(7) = 13
fib(8) = 21
fib(9) = 34
fib(10) = 55
...
fib(93) = 12200160415121876738 /* max using 64-bit math */
...
fib(100) = 354224848179261915075
...
fib(1000) = 43466557686937456435688527675040625802564660517371780402481729089536555417949051890403879840079255169295922593080322634775209689623239873322471161642996440906533187938298969649928516003704476137795166849228875
...
fib(10000) = 336...(2084 digits)...875

Printing to output: integer as sum of powers of 2

I had an exam, and I've been struggling ever since.
You have an array of integers(ex. 13, 6, 21, 4), and I need to make an output that looks like:
13 = 2^3 + 2^2 + 2^0
6 = 2^2 + 2^1
21 = 2^4 + 2^2 + 2^0
4 = 2^2
here's what i've got so far.
#include <stdio.h>
#define MAX 100
int main() {
int niz[MAX], nizb, n, i, ones, k;
while(1) {
printf("Array length: ");
scanf("%d", &n);
if (n<=0 || n>MAX) break;
printf("Array elements: ");
for(i=0;i<n;i++){
scanf("%d", &niz[i]);
if (niz[i] <=0) {
printf("Error! Wrong value. Enter new one: ");
scanf("%d", &niz[i]);
}
}
for(i=0;i<n;i++) {
nizb = niz[i];
ones = 0;
for(k=0; k < 16; k++) {
//What should i do here?
}
}
}
}
I'm stuck here. I dont know how many bits should i use, and how does C sees those bits of integer. I'm using var 'k' to add to a string that is in format '2^3 + 2^2 ...', where k is the value of 'for' iteration. I have made an assumption that length of the integer is 16, but im really not sure since we do this on a sheet of paper.
I want to say BIG THANKS TO EVERYONE!!!
You can calculate how many bits to use by using the sizeof operator and CHAR_BIT:
int bitsPerInt = sizeof(int) * CHAR_BIT;
CHAR_BIT is definied in limits.h.
After you have that limit, you can use the bitwise & operator to extract each bit:
for (k = bitsPerInt - 1; k >= 0; k--)
{
if (nizb & (1U << k))
// output
else
// don't
}
I'll leave the details up to you.
Aside: It looks like you're trying to use niz as an array, but you haven't declared it as one. Does this code even compile? Also, the return value of main should be int.
Not sure what this has to do with twos-complement (which is a particular way of representing negative numbers). What you are trying to do is express an integer as a sum of powers of 2, apparently. Here's the way I'd do it, which isn't necessarily better or worse than the other answers...
void powersum(int n)
{ int powers[sizeof(int) << 3];
int i;
char *sep = "";
printf("%d = ", n);
powers[0] = 0;
for (i = 0; n; n >>= 1, ++i)
powers[i] = n & 1;
while (--i >= 0)
{ if (powers[i])
{ printf("%s2^%d", sep, i);
sep = " + ";
}
}
printf("\n");
}
EDIT: Here's another version that doesn't use the stack-allocated array, but as a tradeoff has to go around the loop more (once for each bit, as opposed to only looping until the highest 1-bit is found):
void powersum2(int n)
{ int i = (sizeof(int) << 3) - 2;
int m = 1 << i;
char *sep = "";
printf("%d = ", n);
while (m)
{ if (n & m)
{ printf("%s2^%d", sep, i);
sep = " + ";
}
m >>= 1;
--i;
}
printf("\n");
}
This is complete conjecture, since I'm not really good with math, but I think I'd go about it like this:
int potency = 0, base = 1;
while(base < NumberInQuestion) {
base *= 2;
++potency;
}
After the loop finishes, you'll know the highest potency which still fits into 'Number'.
Number -= base/2; //Removes the base you just calculated from the number.
printf("2^%d", potency);
Rinse and repeat, until Number falls to 0, which should be at 2^0 at latest.
For your use-case, the code may look somewhat like this:
for(i=0; i < n; ++i) {
int Number = niz[i];
while(Number > 0) {
int potency = 0, base = 1;
do { //Executes at least once, making a number of '1' possible.
base *= 2;
++potency;
} while(base < Number);
Number -= base/2; //Reverts the last step you made, making the 'base' smaller than 'Number'.
printf("2^%d", potency);
}
}
There's a possible alternative, which can give you a more complete picture of things and will save you iterations. For this we use a two-step process.
for(i=0; i < n; ++i) {
int Number = niz[i];
int potency = 0, base = 1;
do { //Executes at least once, making a number of '1' possible.
base *= 2;
++potency;
} while(base < Number);
base /= 2; //Reverses the last iteration.
//At this point, we know the maximum potency, which still fits into the number.
//In regards of base 2, we know the Most Significant Bit.
while(base > 0) {
Number -= base; //Removes the MSD (Most significant digit)
printf("2^%d", potency); //Prints your '1'.
while(base > Number) { //Executes at least once.
base /= 2; //Goes back one potency. (Ends at '0' latest.)
--potency; //For each potency (except for first), it's a '0'.
}
}
}
quotient = niz[i];
int k=0,c[MAX];
while(quotient!=0){
binaryNumber[i++]= quotient % 2; //this will convert your numbers to binary form
quotient = quotient / 2; //and store in reverse in array
}
for(j = 0 ;j<i;j++)
{
if(binaryNumber[j]==1) */e.g binary of 4 is stored in array as 001 ie 1 atpos2*/
{ c[k]=j;
k++;}
}
while(k--)
printf("2^%d +",c[k]);
If you can tolerate a GCC-dependency, a hack on #twalberg's solution get's really nice and small ;)
void powersum(int n)
{
char *sep = "";
printf("%d = ", n);
while (n) {
int pos = 31 - __builtin_clz(n);
printf("%s2^%d", sep, pos);
sep = " + ";
n ^= 1 << pos;
}
printf("\n");
}

Extracting individual digits from a long in C

I'm doing a homework assignment for my course in C (first programming course).
Part of the assignment is to write code so that a user inputs a number up to 9 digits long, and the program needs to determine whether this number is "increasing"/"truly increasing"/"decreasing"/"truly decreasing"/"increasing and decreasing"/"truly decreasing and truly increasing"/"not decreasing and not increasing". (7 options in total)
Since this is our first assignment we're not allowed to use anything besides what was taught in class:
do-while, for, while loops, else-if, if,
break,continue
scanf, printf ,modulo, and the basic operators
(We can't use any library besides for stdio.h)
That's it. I can't use arrays or getchar or any of that stuff. The only function I can use to receive input from the user is scanf.
So far I've already written the algorithm with a flowchart and everything, but I need to separate the user's input into it's distinct digits.
For example, if the user inputs "1234..." i want to save 1 in a, 2 in b, and so on, and then make comparisons between all the digits to determine for example whether they are all equal (increasing and decreasing) or whether a > b >c ... (decreasing) and so on.
I know how to separate each digit by using the % and / operator, but I can't figure out how to "save" these values in a variable that I can later use for the comparisons.
This is what I have so far:
printf("Enter a positive number : ");
do {
scanf ("%ld", &number);
if (number < 0) {
printf ("invalid input...enter a positive integer: ");
continue;
}
else break;
} while (1);
while (number < 0) {
a = number % 10;
number = number - a;
number = number / 10;
b = a;
}
Why not scan them as characters (string)? Then you can access them via an array offset, by subtracting the offset of 48 from the ASCII character code. You can verify that the character is a digit using isdigit from ctype.h.
EDIT
Because of the incredibly absent-minded limitations that your professor put in place:
#include <stdio.h>
int main()
{
int number;
printf("Enter a positive number: ");
do
{
scanf ("%ld", &number);
if (number < 0)
{
printf ("invalid input...enter a positive integer: ");
continue;
}
else break;
} while (1);
int a = -1;
int b = -1;
int c = -1;
int d = -1;
int e = -1;
int f = -1;
int g = -1;
int h = -1;
int i = -1;
while (number > 0)
{
if (a < 0) a = number % 10;
else if (b < 0) b = number % 10;
else if (c < 0) c = number % 10;
else if (d < 0) d = number % 10;
else if (e < 0) e = number % 10;
else if (f < 0) f = number % 10;
else if (g < 0) g = number % 10;
else if (h < 0) h = number % 10;
else if (i < 0) i = number % 10;
number /= 10;
}
/* Printing for verification. */
printf("%i", a);
printf("%i", b);
printf("%i", c);
printf("%i", d);
printf("%i", e);
printf("%i", f);
printf("%i", g);
printf("%i", h);
printf("%i", i);
return 0;
}
The valid numbers at the end will be positive, so those are the ones you validate to meet your different conditions.
Since you only need to compare consecutive digits, there is an elegant way to do this without arrays:
int decreasing = 2;
int increasing = 2;
while(number > 9)
{
int a = number % 10;
int b = (number / 10) % 10;
if(a == b)
{
decreasing = min(1, decreasing);
increasing = min(1, increasing);
}
else if(a > b)
decreasing = 0;
else if(a < b)
increasing = 0;
number /= 10;
}
Here, we walk through the number (by dividing by 10) until only one digit remains. We store info about the number up to this point in decreasing and increasing - a 2 means truly increasing/decreasing, a 1 means increasing/decreasing, and a 0 means not increasing/decreasing.
At each step, a is the ones digit and b is the tens. Then, we change increasing and decreasing based on a comparison between a and b.
At the end, it should be easy to turn the values of increasing and decreasing into the final answer you want.
Note: The function min returns the smaller of its 2 arguments. You should be able to write your own, or replace those lines with if statements or conditionals.
It's stupid to ask you to do loops without arrays --- but that's your teacher's fault, not yours.
That being said, I would do something like this:
char c;
while (1) {
scanf("%c", &c);
if (c == '\n') /* encountered newline (end of input) */
break;
if (c < '0' || c > '9')
break; /* do something to handle bad characters? */
c -= '0';
/*
* At this point you've got 0 <= c < 9. This is
* where you do your homework :)
*/
}
The trick here is that when you type numbers into a program, you send the buffer all at once, not one character at a time. That means the first scanf will block until the entire string (i.e. "123823" or whatever) arrives all at once, along with the newline character ( '\n' ). Then this loop parses that string at its leisure.
Edit For testing the increasing/decreasing-ness of the digits, you may think you need to store the entire string, but that's not true. Just define some additional variables to remember the important information, such as:
int largest_digit_ive_seen, smallest_digit_ive_seen, strict_increasing_thus_far;
etc. etc.
Let us suppose you have this number 23654
23654 % 10000 = 2 and 3654
3654 % 1000 = 3 and 654
654 % 100 = 6 and 54
54 % 10 = 5 and 4
4
This way you can get all the digits. Of course, you have to know if the number is greater than 10000, 1000, 100 or 10, in order to know the first divisor.
Play with sizeof to get the size of the integer, in order to avoid a huge if...else statement
EDIT:
Let us see
if (number>0) {
// Well, whe have the first and only digit
} else if (number>10) {
int first_digit = number/10;
int second_digit = number % 10;
} else if (number>100) {
int first_digit = number/100;
int second_digit = (number % 100)/10;
int third_digit = (number % 100) % 10;
} ...
and so on, I suppose
// u_i is the user input, My homework asked me to extract a long long, however, this should also be effective for a long.
int digits = 0;
long long d_base = 1;
int d_arr[20];
while (u_i / d_base > 0)
{
d_arr[digits] = (u_i - u_i / (d_base * 10) * (d_base * 10)) / d_base;
u_i -= d_arr[digits] * d_base;
d_base *= 10;
digits++;
}
EDIT: the extracted individual digit now lives in the int array d_arr. I'm not good at C, so I think the array declaration can be optimized.
Here's a working example in plain C :
#include <stdio.h>
unsigned long alePow (unsigned long int x, unsigned long int y);
int main( int argc, const char* argv[] )
{
int enter_num, temp_num, sum = 0;
int divisor, digit, count = 0;
printf("Please enter number\n");
scanf("%d", &enter_num);
temp_num = enter_num;
// Counting the number of digits in the entered integer
while (temp_num != 0)
{
temp_num = temp_num/10;
count++;
}
temp_num = enter_num;
// Extracting the digits
printf("Individual digits in the entered number are ");
do
{
divisor = (int)(alePow(10.0, --count));
digit = temp_num / divisor;
temp_num = temp_num % divisor;
printf(" %d",digit);
sum = sum + digit;
}
while(count != 0);
printf("\nSum of the digits is = %d\n",sum);
return 0;
}
unsigned long alePow(unsigned long int x, unsigned long int y) {
if (x==0) { return 0; }
if (y==0||x==1) { return 1; }
if (y==1) { return x; }
return alePow(x*x, y/2) * ((y%2==0) ? 1 : x);
}
I would suggest loop-unrolling.
int a=-1, b=-1, c=-1, d=-1, e=1, f=-1, g=-1, h=-1, i=-1; // for holding 9 digits
int count = 0; //for number of digits in the given number
if(number>0) {
i=number%10;
number/=10;
count++;
}
if(number>0) {
h=number%10;
number/=10;
count++;
}
if(number>0) {
g=number%10;
number/=10;
count++;
}
....
....
/* All the way down to the storing variable a */
Now, you know the number of digits (variable count) and they are stored in which of the variables. Now you have all digits and you can check their "decreasing", "increasing" etc with lots of if's !
I can't really think of a better soltion given all your conditions.

storing more than 2 power 31 on a 32-bit system

I have to write a program that can calculate the powers of 2 power 2010 and to find the sum of the digits. eg:
if `2 power 12 => gives 4096 . So 4+0+9+6 = 19 .
Now i need to find the same for 2 power 2010.
Please help me to understand.
Here's something to get you started:
char buf[2010]; // 2^2010 < 10^2010 by a huge margin, so buffer size is safe
snprintf(buf, sizeof buf, "%.0Lf", 0x1p2010L);
You have to either use a library that supplies unlimited integer length types (see http://en.wikipedia.org/wiki/Bignum ), or implement a solution that does not need them (e.g. use a digit array and implement the power calculation on the array yourself, which in your case can be as simple as addition in a loop). Since this is homework, probably the latter.
Knowing 2^32, how would you calculate 2^33 with pen and paper?
2^32 is 4294967296
4294967296
* 2
----------
8589934592
8589934592 is 2^33; sum of digits is 8+5+8+9+...+9+2 (62)
Just be aware that 2^2011 is a number with more than 600 digits: not that many to do by computer
GMP is perhaps the best, fastest free multi-architecture library for this. It provides a solid foundation for such calculations, including not only addition, but parsing from strings, multiplication, division, scientific operations, etc.
For literature on the algorithms themselves, I highly recommend The Art of Computer Programming, Volume 2: Seminumerical Algorithms by Donald Knuth. This book is considered by many to be the best single reference for the topic. This book explains from the ground up how such arithmetic can take place on a machine that can only do 32-bit arithmetic.
If you want to implement this calculation from scratch without using any tools, the following code block requires requires only the following additional methods to be supplied:
unsigned int divModByTen(unsigned int *num, unsigned int length);
bool isZero(unsigned int *num, unsigned int length);
divModByTen should divide replace num in memory with the value of num / 10, and return the remainder. The implementation will take some effort, unless a library is used. isZero just checks if the number is all zero's in memory. Once we have these, we can use the following code sample:
unsigned int div10;
int decimalDigitSum;
unsigned int hugeNumber[64];
memset(twoPow2010, 0, sizeof(twoPow2010));
twoPow2010[63] = 0x4000000;
// at this point, twoPow2010 is 2^2010 encoded in binary stored in memory
decimalDigitSum = 0;
while (!izZero(hugeNumber, 64)) {
mod10 = divModByTen(&hugeNumber[0], 64);
decimalDigitSum += mod10;
}
printf("Digit Sum:%d", decimalDigitSum);
This takes only a few lines of code in Delphi... :)
So in c must be the same or shorter.
function PowerOf2(exp: integer): string;
var
n : integer;
Digit : integer;
begin
result := '1';
while exp <> 0 do
begin
Digit := 0;
for n := Length(result) downto 1 do
begin
Digit := (ord(result[n]) - ord('0')) * 2 + Digit div 10;
result[n] := char(Digit mod 10 + ord('0'))
end;
if Digit > 9 then
result := '1' + result;
dec(exp);
end;
end;
-----EDIT-----
This is 1-to-1 c# version.
string PowerOf2(int exp)
{
int n, digit;
StringBuilder result = new StringBuilder("1");
while (exp != 0)
{
digit = 0;
for (n = result.Length; n >= 1; n--)
{
digit = (result[n-1] - '0') * 2 + digit / 10;
result[n-1] = Convert.ToChar(digit % 10 + '0');
}
if (digit > 9)
{
result = new StringBuilder("1" + result.ToString());
}
exp--;
}
return result.ToString();
}
int Sum(string s)
{
int sum = 0;
for (int i = 0; i < s.Length; i++)
{
sum += s[i] - '0';
}
return sum;
}
for (int i = 1; i < 20; i++)
{
string s1s = PowerOf2(i);
int sum = Sum(s1s);
Console.WriteLine(s1s + " --> " + sum);
}
Here's how you can calculate and print 22010:
#include <stdio.h>
#include <string.h>
void AddNumbers(char* dst, const char* src)
{
char ddigit;
char carry = 0;
while ((ddigit = *dst) != '\0')
{
char sdigit = '0';
if (*src != '\0')
{
sdigit = *src++;
}
ddigit += sdigit - '0' + carry;
if (ddigit > '9')
{
ddigit -= 10;
carry = 1;
}
else
{
carry = 0;
}
*dst++ = ddigit;
}
}
void ReverseString(char* s)
{
size_t i, n = strlen(s);
for (i = 0; i < n / 2; i++)
{
char t = s[i];
s[i] = s[n - 1 - i];
s[n - 1 - i] = t;
}
}
int main(void)
{
char result[607], tmp[sizeof(result)];
int i;
memset (result, '0', sizeof(result));
result[0] = '1';
result[sizeof(result) - 1] = '\0';
for (i = 0; i < 2010; i++)
{
memcpy(tmp, result, sizeof(result));
AddNumbers(result, tmp);
}
ReverseString(result);
printf("%s\n", result);
return 0;
}
You can now sum up the individual digits.

Resources