Skip to content

Instantly share code, notes, and snippets.

@bloopletech
Created March 20, 2010 00:09
Show Gist options
  • Save bloopletech/338338 to your computer and use it in GitHub Desktop.
Save bloopletech/338338 to your computer and use it in GitHub Desktop.
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "bigint.h"
/* this library provides for a bigint type, which can hold numbers of an unlimited length.
You can add them together as well.*/
/*this function allocates & returns a bigint struct*/
//given a bigint that is _already_ allocated, initialize it with zero.
void newnum(bigint* num)
{
num->number = (digit*)malloc(1);
num->number[0] = 0;
num->length = 1;
}
//given a bigint that is _already_ allocated,
//and given a number string, allocate the bigint
void newnumf(bigint* num, char* numb)
{
int numbl = strlen(numb);
digit* out = (digit*)malloc(numbl);
for(int i = 0; i < numbl; i++)
{
out[i] = numb[i] - CHARZERO_ABOVEINTZERO;
}
num->number = out;
num->length = numbl;
}
//this function allocates and returns a bigint pointer, with the number numb allocated
bigint* newnumc(char* numb)
{
//allocate storage for the bigint
bigint* num = (bigint*)malloc(sizeof(bigint));
int numbl = strlen(numb);
int numbll = numbl - 1;
//allocate storage for the number, in the right length
digit* out = (digit*)malloc(numbl);
for(int i = 0; i < numbl; i++)
{
out[i] = numb[numbll - i] - CHARZERO_ABOVEINTZERO;
}
num->number = out;
num->length = numbl;
//return the new bigint
return num;
}
//makes a deep copy of from, and put it in to
void numcpy(bigint* to, bigint* from)
{
to->number = (digit*)realloc(to->number, from->length);
//copy from's number into to's number
int fl = from->length;
digit* tn = to->number;
digit* fn = from->number;
for(int i = 0; i < fl; i++)
{
tn[i] = fn[i];
}
//copy from's length into two's length
to->length = from->length;
}
//clear a bigint that was created by newnumc
void delnum(bigint* num)
{
//free the bigint's number
free(num->number);
//free the bigint
free(num);
}
//adds a to b, and stores the result in result
void add(bigint* a, bigint* b, bigint* result)
{
//store the length of ac and bc
int al = a->length;
int bl = b->length;
int length = al;
if(bl > al) length = bl;
//allocate storage for the length of the result
int cl = length + 1;
//allocate space for a and b's number
digit* ac = a->number;
digit* bc = b->number;
//allocate space for the result
digit* out = (digit*)malloc(cl);
int temp = 0, carry = 0;
for(int i = 0; i < length; i++)
{
if(i >= al) temp = bc[i] + carry;
else if(i >= bl) temp = ac[i] + carry;
else temp = ac[i] + bc[i] + carry;
if(temp > 9)
{
carry = 1;
temp -= 10;
}
else
{
carry = 0;
}
out[i] = temp;
}
//fix up the last digit of carry/the length of carry
if(carry == 0)
{
out = (digit*)realloc(out, length);
result->length = length;
}
else
{
out[length] = carry;
result->length = cl;
}
result->number = out;
}
//print out a bigint's value
void print(bigint* num)
{
digit* numc = num->number; //NOT A CHAR ARRAY
int numl = num->length;
int numll = numl - 1;
char* out = (char*)malloc(numl + 1);
for(int i = 0; i < numl; i++)
{
out[i] = numc[numll - i] + CHARZERO_ABOVEINTZERO;
}
out[numl] = '\0';
puts(out);
free(out);
}
//print out a bigint's value
void fprint(bigint* num, FILE *file)
{
digit* numc = num->number; //NOT A CHAR ARRAY
int numl = num->length;
int numll = numl - 1;
char* out = (char*)malloc(numl + 1);
for(int i = 0; i < numl; i++)
{
out[i] = numc[numll - i] + CHARZERO_ABOVEINTZERO;
}
out[numl] = '\0';
fputs(out, file);
putc('\n', file);
free(out);
}
/*void fbprint(bigint* num, FILE *file)
{
digit* numc = num->number; //NOT A CHAR ARRAY
int numl = num->length;
int i = 0;
long whattowrite = 0;
while((numl - i) >= 10)
{
whattowrite = (numc[i++] * 10^0)
+ (numc[i++] * 10^1)
+ (numc[i++] * 10^2)
+ (numc[i++] * 10^3)
+ (numc[i++] * 10^4)
+ (numc[i++] * 10^5)
+ (numc[i++] * 10^6)
+ (numc[i++] * 10^7)
+ (numc[i++] * 10^8)
+ (numc[i++] * 10^9)
+ whattowrite;
fwrite(whattowrite, sizeof(int), 1, file);
if(whattowrite > INT_MAX)
{
whattowrite -= INT_MAX;
}
}
if((numl - i) == 9)
{
whattowrite = (numc[i++] * 10^0)
+ (numc[i++] * 10^1)
+ (numc[i++] * 10^2)
+ (numc[i++] * 10^3)
+ (numc[i++] * 10^4)
+ (numc[i++] * 10^5)
+ (numc[i++] * 10^6)
+ (numc[i++] * 10^7)
+ (numc[i++] * 10^8)
+ whattowrite;
fwrite(whattowrite, sizeof(int), 1, file);
if(whattowrite > INT_MAX)
{
whattowrite -= INT_MAX;
}
fwrite(
int numll = numl - 1;
char* out = (char*)malloc(numl + 1);
for(int i = 0; i < numl; i++)
{
out[i] = numc[numll - i] + CHARZERO_ABOVEINTZERO;
}
out[numl] = '\0';
fputs(out, file);
putc('\n', file);
free(out);
*/
//this is the difference between the ASCII code for 0 and the integer 0
#define CHARZERO_ABOVEINTZERO 48
//This define defines a single byte unsigned integer
//if your system uses a different type for this kind of integer, substitute it here
typedef unsigned char digit;
//the type digit* represents an array of digit s
typedef struct
{
digit* number; ///this is a pointer to an array of digit s
int length; // this is the length of the arrat referenced by number
} bigint;
void newnum(bigint*);
void newnumf(bigint*, char*);
bigint* newnumc(char*);
void numcpy(bigint*, bigint*);
void delnum(bigint*);
void add(bigint*, bigint*, bigint*);
void print(bigint*);
void fprint(bigint*, FILE*);
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <time.h>
#include "bigint.h"
#define MAX_INT_DIGITS 10
#define MAX_LONG_DIGITS 20
/*this function calculates the fibonacci sequence*/
int main(int argc, char** argv)
{
printf("WARNING: Calculating large numbers of iterations can take a long time (> 10 minutes).\n");
printf("The output file can also grow very large. The output file for 100,000 iterations is ~1GB.\n");
printf("This program will use ~100%% CPU time during calculation.\n");
printf("The program does not check for errors while calculating.\n");
printf("If an error occurs during calculation, the operation of this program is undefined.\n");
/*this function uses the following method to calculate the fibonacci sequence:
a = 1, b = 1
loop:
c = a + b //c[i] = c[i - 1] + c[i - 2]
a = b //c[i - 2] = c[i - 1]
b = c //c[i - 1] = c[i]
in each loop, this seuence adds the two numbers together and takes the summands and
their result, and moves them down the sequence. This sequence does not requre storage
of any more than the last two numbers in the sequence.*/
//the user is asked to press a key at the end of the program.
//The read statement at the end has to store the result somewhere,
//so it's put in here.
char temp = 'a';
//create 3 bigints: 2 for the summands, and one for the result
bigint* a = newnumc("1");
bigint* b = newnumc("1");
bigint* c = newnumc("0");
//get how many iterations? the user wants
int size = 0;
if(argc == 2)
{
size = atoi(argv[1]);
}
else if(argc == 4)
{
a = newnumc(argv[1]);
b = newnumc(argv[2]);
size = atoi(argv[3]);
}
else
{
printf("How many iterations do you want? ");
scanf("%i", &size);
}
char* fname = (char*)malloc(9 + MAX_INT_DIGITS + MAX_LONG_DIGITS + 1);
sprintf(fname, "fib-%i-%i.txt", size, time(NULL));
FILE *file = fopen(fname, "w");
//print the first two iterations of the fibonacci sequence
if(size == 1)
{
fprint(a, file);
}
else if(size >= 2)
{
fprint(a, file);
fprint(b, file);
}
//the program prints out the first two iterations separate from the rest
size -= 2;
//loop for the required number of iterations
int i = 0;
while(i < size)
{
//add the summands together and store the result in c
add(a, b, c);
//print the result
fprint(c, file);
//move b and c down the sequence
//see description at the top for more information
numcpy(a, b);
numcpy(b, c);
i++;
}
//clear a, b, and the result
delnum(a);
delnum(b);
delnum(c);
fflush(file);
fclose(file);
free(fname);
return 0;
}
@Eng-K4M4
Copy link

Very simple and very interesting!

@assyrianic
Copy link

  1. Casting malloc 👎
  2. Freeing member pointers without setting them back to NULL 👎

Everything else is good.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment