Arithmetic with base 256 number system

浪子不回头ぞ 提交于 2019-12-13 09:47:54

问题


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("\n");
}

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));
}

回答1:


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:

  • Cant make value propagate through carry
  • Fast bignum square computation
  • Floating Point Divider Hardware Implementation Details
  • Building a logarithm function in C without using float type
  • Schönhage-Strassen multiplication using NTT

[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
 }


来源:https://stackoverflow.com/questions/45218772/arithmetic-with-base-256-number-system

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!