Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

C: Representation of Big Integers

Tags:

c

So, let's say I've created a struct of 3 32-bit integers that act as a 96-bit integer.

typedef struct {
    unsigned int x, y, z;
} Int96; 

Let's take this to mean that int x is the first integer to be filled. Before it overflows, y is incremented and x is refreshed back to 0. z functions similarly, but takes care of y's overflow.

How would I go about printing the value stored in this struct? Surely I can't directly print out the full value without causing an overflow on my system.

like image 372
wadda_wadda Avatar asked Sep 29 '14 17:09

wadda_wadda


People also ask

What is big integer in C?

The BIGINT data type is a machine-independent method for representing numbers in the range of -2 63-1 to 2 63-1. ESQL/C provides routines that facilitate the conversion from the BIGINT data type to other data types in the C language. The BIGINT data type is internally represented with the ifx_int8_t structure.

What is big integer?

BigInteger provides analogues to all of Java's primitive integer operators, and all relevant methods from java. lang. Math. Additionally, BigInteger provides operations for modular arithmetic, GCD calculation, primality testing, prime generation, bit manipulation, and a few other miscellaneous operations.

How do you store big integers?

Below are the steps: Take the large number as input and store it in a string. Create an integer array arr[] of length same as the string size. Iterate over all characters (digits) of string str one by one and store that digits in the corresponding index of the array arr.

Which data type can hold 10 digit integer numbers in C?

The INTEGER data type stores whole numbers that range from -2,147,483,647 to 2,147,483,647 for 9 or 10 digits of precision. The number 2,147,483,648 is a reserved value and cannot be used. The INTEGER value is stored as a signed binary integer and is typically used to store counts, quantities, and so on.


1 Answers

The first step is writing general purpose arithmetic routines for your Int96:

void Add96(Int96 *a, const Int96 *b) {
    // add b to a
    a->x += b->x;
    a->y += b->y;
    a->z += b->z;
    if (a->y < b->y) a->z++;
    if (a->x < b->x && ++a->y == 0) a->z++; }
void Sub96(Int96 *a, const Int96 *b);
void Mul96(Int96 *a, const Int96 *b);
void Div96(Int96 *a, const Int96 *b);
void Mod96(Int96 *a, const Int96 *b);

With those you can write:

void print96(const Int96 *val) {
    Int96 ten = { 10, 0, 0 };
    Int96 div = *val;
    Int96 mod = *val;
    Div96(&div, &ten);
    Mod96(&mod, &ten);
    if (div.x || div.y || div.z) print96(&div);
    putchar('0' + mod.x); }

You can make this more efficient by writing a DivMod96uint function that does the div and mod in a single step and takes an unsigned (rather than an Int96) for the second argument and returns the mod. You can also avoid an extra copy per digit by having a print96destructive function that overwrites its argument, and have print96 just make a copy and then call that:

void print96destructive(Int96 *val) {
    unsigned mod = DivMod96ui(val, 10);
    if (val->x || val->y || val->z) print96destructive(val);
    putchar('0' + mod); }
void print96(const Int96 *val) {
    Int96 v = *val;
    print96destructive(&v); }

unsigned DivMod96ui(Int96 *a, unsigned b) {
    unsigned mod = a->z % b;
    a->z /= b;
    uint64_t y = a->y + ((uint64_t)mod << 32);
    mod = y % b;
    a->y = y / b;
    uint64_t x = a->x + ((uint64_t)mod << 32);
    mod = x % b;
    a->x = x / b;
    return mod; }
like image 80
Chris Dodd Avatar answered Oct 20 '22 21:10

Chris Dodd