Warm tip: This article is reproduced from stackoverflow.com, please click
c

How to convert 32+ bit number (38bit) into a string on a 32bit system, smartly in C

发布于 2020-03-28 23:17:42

How would you go about turning a 38bit number into a string if the largest data format available is 32bit?

The decimal representation is needed, the string is needed so as to save the number into a csv file.

The question is complete "as is", there is no need to look for the perceived true intention of the question elsewhere.

Questioner
Horst
Viewed
18
r3mainer 2020-01-31 20:36

This ought to work. It uses a static array to store the results, so you'll need to arrange for these to be copied elsewhere if you don't want them to be clobbered by the next call.

The algorithm is simple enough. It just uses long division to divide the number by 10 repeatedly, and uses the remainder at each iteration to build the text output. I'm assuming the input consists of an array of 5 bytes in big-endian order. You can easily change this to work with larger numbers by changing the value of BIG_WORD_LENGTH. I should also point out that this function won't work with negative numbers at all. You can speed it up a bit by breaking out of the main loop when n reaches zero.

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

#define BIG_WORD_LENGTH 5

// Length of output is at most ceil(BIG_WORD_LENGTH * log(256) / log(10))
// The following is a slight overestimate, but close enough
#define BIG_WORD_STRLEN (3 + (BIG_WORD_LENGTH) * 5 / 2)

typedef uint8_t big_word[BIG_WORD_LENGTH];

char *big_word_2_str(big_word num) {
    // Make a local copy of the number
    big_word n;
    for (int i=0; i<BIG_WORD_LENGTH; i++) {
        n[i] = num[i];
    }

    // Result goes here
    static char result[BIG_WORD_STRLEN];
    int p = BIG_WORD_STRLEN-1;
    result[p--] = '\0';

    // Calculate digits in base 10
    for (int i=1; i<BIG_WORD_STRLEN; i++) {
        int x, tmp = 0;
        for (int j=0; j<BIG_WORD_LENGTH; j++) {
            x = n[j];
            x += tmp << 8;
            tmp = x % 10;
            n[j] = x / 10;
        }
        result[p--] = '0' + tmp;
    }

    // Trim leading zeros
    while (++p < BIG_WORD_STRLEN-2 && result[p] == '0');

    return result + p;
}


// Test:
int main() {
    // 0x492559f64f = 314159265359
    big_word x = { 0x49, 0x25, 0x59, 0xf6, 0x4f };
    puts(big_word_2_str(x));
    return 0;
}