Home > Software engineering >  How to convert large HEX string to INT in C
How to convert large HEX string to INT in C

Time:09-18

I got large HEX string in result into int i could be more than 10 ^ 30, and I converted in hex. I need sum (3 hex string) and remove last 12 numbers.

hex example "000000000000000000000000bd4c61f945644cf099d41ab8a0ab2ac5d2533835", "000000000000000000000000000000000000000000000000f32f5908b7f3c000", "00000000000000000000000000000000000000000000000000e969cd49be4000". And I need to sum them and get result into int. Thank you

I "made" a little two functions and they work but i think could be better, and they dont convert to normal integer number


    // convert hex to unsigned char decimal
    unsigned char div10(unsigned char *hex, unsigned size)
    {
        unsigned rem = 0;
        for(int i = 0; i < size; i  )
        {
            unsigned n = rem * 256   hex[i];
            hex[i] = n / 10;
            rem = n % 10;
        }
        return rem;
    }
    
    
    unsigned char hex_to_dec_summer(char *local){
        unsigned char result[32]={0};
        unsigned char output[18]={};
    
        char input[64];
        strcpy(input, local);
    
        unsigned char hexnr[sizeof(input)/2]={}; 
        for (int i=0; i<sizeof(input)/2; i  ) {
            sscanf(&input[i*2], "xd", &hexnr[i]);
        }
        
        
        unsigned char hexzero[32] = {0};
        unsigned i = 0;
        while(memcmp(hexnr, hexzero, sizeof(hexnr)) != 0 && i < sizeof(result))
        {
            result[sizeof(result) - i - 1] = div10(hexnr, sizeof(hexnr));
            i  ;
        }
        printf("\n");
    
        for(unsigned j = 0; j < sizeof output; j  )
        {
            output[j]=result[j];
            printf("%d", output[j]);
        }
        output[18]='\0';
    }

I know how its make in python3 -> int(hex_number, 16)/(10**12) - like that but i need it in c

CodePudding user response:

The reason this sort of thing works so easily in Python is that, unusually, Python supports arbitrary-precision integers natively.

Most languages, including C, use fixed sizes for their native types. To perform arbitrary-precision arithmetic, you generally need a separate library, such as GMP.

Here is a basic example of using GMP to solve your problem:

#include <stdio.h>
#include <gmp.h>

char *inputs[] = {
    "000000000000000000000000bd4c61f945644cf099d41ab8a0ab2ac5d2533835",
    "000000000000000000000000000000000000000000000000f32f5908b7f3c000",
    "00000000000000000000000000000000000000000000000000e969cd49be4000"
};

int main()
{
    char outstr[100];
    mpz_t x; mpz_init(x);
    mpz_t y; mpz_init(y);
    mpz_t sum; mpz_init(sum);
    mpz_t ten; mpz_init_set_si(ten, 10);
    mpz_t fac; mpz_init(fac);
    mpz_pow_ui(fac, ten, 12);        /* fac = 10**12 */

    int i;
    for(i = 0; i < 3; i  ) {
        mpz_set_str(x, inputs[i], 16);
        mpz_tdiv_q(y, x, fac);
        mpz_add(sum, sum, y);        /* sum  = x / fac */
    }

    printf("%s\n", mpz_get_str(outstr, 10, sum));
}

The code is a bit verbose, because arbitrary-precision integers (that is, variables of type mpz_t) have nontrivial memory allocation requirements, and everything you do with them requires explicit function calls. (Working with extended types like this would be considerably more convenient in a language with good support for object-oriented programming, like C .)

To compile this, you'll need to have GMP installed. On my machine, I used

cc testprog.c -lgmp

When run, this program prints

1080702647035076263416932216315997551

Or, if I changed 10 to 16 in the last line, it would print d022c1183a2720991b1fea332a6d6f.

It will make a slight difference whether you divide by 1012 and then sum, or sum and then divide. To sum and then divide, you could get rid of the line mpz_tdiv_q(y, x, fac) inside the loop, change mpz_add(sum, sum, y) to mpz_add(sum, sum, x), and add the line

mpz_tdiv_q(sum, sum, fac);

outside the loop, just before printing.

CodePudding user response:

It's fairly straight forward to add up the (in this case hex) digits of two strings.

This doesn't try to be "optimal", but it does give a sum (as a string of hex digits). vals[0] acts as the accumulator.

When OP clarifies what is meant by "I need sum (3 hex string) and remove last 12 numbers", this answer could be extended.

If more speed is needed, the accumulator could be allocated and used as an array of uint8_t's (saving converting back to ASCII hex until a final total is available.) Also the LUT to convert ASCII hex to '0-F' could be 'binary' (not requiring the subtraction of ASCII character values.)

Anyway...

#include <stdio.h>

char *vals[] = {
    "000000000000000000000000bd4c61f945644cf099d41ab8a0ab2ac5d2533835",
    "000000000000000000000000000000000000000000000000f32f5908b7f3c000",
    "00000000000000000000000000000000000000000000000000e969cd49be4000",
};

char *frmHex =
    "................................................0000000000......"
    ".777777..........................WWWWWW.........................";

char *tohex = "0123456789ABCDEF";

void addTo( char *p0, char *p1 ) {
    printf( "  %s\n  %s\n", p0, p1 );

    char *px = p0   strlen( p0 ) - 1;
    char *py = p1   strlen( p1 ) - 1;

    for( int carry = 0; px >= p0 && py >= p1; px--, py-- ) {
        int val = *px - frmHex[ *px ]   *py - frmHex[ *py ]   carry;

        carry = val / 0x10; *px = tohex[ val % 0x10 ];
    }
    printf( "= %s\n\n", p0 );
}

int main() {
    addTo( vals[ 0 ], vals[ 1 ] );
    addTo( vals[ 0 ], vals[ 2 ] );

    return 0;
}

Output

  000000000000000000000000bd4c61f945644cf099d41ab8a0ab2ac5d2533835
  000000000000000000000000000000000000000000000000f32f5908b7f3c000
= 000000000000000000000000BD4C61F945644CF099D41AB993DA83CE8A46F835

  000000000000000000000000BD4C61F945644CF099D41AB993DA83CE8A46F835
  00000000000000000000000000000000000000000000000000e969cd49be4000
= 000000000000000000000000BD4C61F945644CF099D41AB994C3ED9BD4053835

If this were to progress (and use binary accumulators), 'compaction' after summing would quickly lead into integer division (that could be done simply with shifting and repeated subtraction.) Anyway...

  • Related