Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Welcome To Ask or Share your Answers For Others

Categories

0 votes
420 views
in Technique[技术] by (71.8m points)

c - Arithmetic with base 256 number system

I am working on a project right now where I need to perform calculations for numbers with base 256. I am reading bytes of a file and storing it in an array of uint8_t (a.k.a unsigned char or BYTE). The largest supported number data type doesn't satisfy the needs of my project. So the array of bytes is acting like a custom length/size data type (BigInt).

I now need to perform arithmetic on it like: -1, /2, %2.

For example this is how addition looks like to demonstrate how my numbers should work:

9   + 1 = (10)
99  + 1 = (100)
255 + 1 = (1)+(0)<<8
255 + 2 = (1)+(1)<<8

Note: First one's is 10 as in 10 is occupying 1 digit whereas the third one is 1 0 as in it's occupying 2 digits. Also I cant convert them to integers because I have to deal with huge numbers.

I am racking my brain trying to think of ways to implement this in C but to no avail.

My code so far:

#include<stdio.h>
#include<string.h>
#include<stdint.h>
#include<stdlib.h>

typedef uint8_t BYTE;
BYTE buffer[1000000000];

void n(){
    printf("
");
}

int main()
{
    uint32_t  x;
    x = 0; 
    int _len,y;
    char * test    = "test.bin";
    FILE * inptr = fopen(test,"rb");
    uint32_t i=0;
    while(fread(&buffer[i],1,1,inptr));
}
See Question&Answers more detail:os

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome To Ask or Share your Answers For Others

1 Answer

0 votes
by (71.8m points)

So you have power of 2 operations which can be easily converted to bit operations... no bigint lib is needed for such triviality. Let assume you got number

const int n=1000000000; // number size in bytes
BYTE x[n]; // number bytes let num[0] be LSW (least signifficant Word)

So the operations involved are:

  1. mod: y = x%2 = x&1

    this is O(1)

    BYTE y = x[0]&1;
    

    result is single bit so no need to store it as bigint

  2. div: y = x/2 = x>>1

    this is O(n) and the result is also bigint so

    int i;
    BYTE y[n]; // result
    BYTE cy; // carry flag
    for (cy=0,i=n-1;i>=0;i--) // process all words from MSW to LSW
     {
     y[i] = ((x[i]>>1)&0x7F) | cy; // bitshifted word + last carry
     cy = (x[i]<<7)&0x80; // carry is shifted out lsb of word shifted to msb position
     }
    
  3. dec: y=x-1

    this is O(n) and the result is also bigint so

    int i;
    BYTE y[n]; // result
    BYTE cy; // carry flag
    for (cy=1,i=0;(i<n)&&(cy);i++) // process all words from LSW to MSW
     {
     y[i] = (x[i]-cy)&0xFF; // y[i] = sbc x[i],0
     cy = (x[i]==0x00); // carry
     }
    

Hope I did not make some silly syntax error or something as I coded this directly into here...

Both O(n) operations can be done in-place you just need to buffer actual x[i] value or compute carry before x[i] change and buffer old carry

In your case I would use 32bit (DWORD) or 64bit (QWORD) instead of 8bit (BYTE) that will boost the speed as the ALU on most computers is 32 or 64 bit anyway

If you're interested in implementing more of the bigint stuff see:

[Edit1] dec for MSW first

int i;
BYTE y[n]; // result
BYTE cy; // carry flag
for (cy=1,i=n-1;(i>=0)&&(cy);i--) // process all words from LSW to MSW
 {
 y[i] = (x[i]-cy)&0xFF; // y[i] = sbc x[i],0
 cy = (x[i]==0x00); // carry
 }

and in-place:

int i;
BYTE cy; // carry flag
for (cy=1,i=n-1;(i>=0)&&(cy);i--) // process all words from LSW to MSW
 {
 x[i] = (x[i]-cy)&0xFF; // y[i] = sbc x[i],0
 if (x[i]==0xFF) cy=1; // carry
 }

与恶龙缠斗过久,自身亦成为恶龙;凝视深渊过久,深渊将回以凝视…
Welcome to OStack Knowledge Sharing Community for programmer and developer-Open, Learning and Share
Click Here to Ask a Question

...