c - c中任意精度数字到ascii

标签 c math arbitrary-precision

我有一个uint8_t *包含任意精度数字 bigendian 编码的数组。

我想得到它的十进制 Ascii 表示形式。所以我需要编写一个返回 char * 的函数.

由于硬件限制,我正在使用的环境不允许我导入任何任意精度库。

我确信我可以阅读一些内容来轻松实现它。

例如由以下十六进制定义的数字 d53ceb9d32c6ca06应由 15365415089075571206 表示.

最佳答案

这是一个应该有效的方法。请注意,它会破坏性地修改您传递给它的 bigint,因此如果您关心那里的值,请在调用该方法之前将其复制到临时临时缓冲区。

此外,这不是您可以编写的最优化版本,但如果您询问如何在这里执行此操作,您可能还不关心对此进行微优化。

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

bool is_zero(uint8_t *bigi_data, int bigi_size) {
    int i = 0;

    while((i < bigi_size) && (bigi_data[i] == 0)) {
        i++;
    }
    return (i >= bigi_size);
}

uint8_t bigdivmod(uint8_t *bigi_data, int bigi_size, uint8_t divisor) {
    int i = 0;
    uint16_t ans = 0;

    while((i < bigi_size) && (bigi_data[i] == 0)) {
        i++;
    }
    for (; i < bigi_size; i++) {
        ans = ans*256 + bigi_data[i];
        bigi_data[i] = ans / divisor;
        ans = ans % divisor;
    }
    return (uint8_t)ans;
}

static const char *digits = "0123456789abcdefghijklmnopqrstuvwxyz";

char *bigitoa(uint8_t *bigi_data, int bigi_size, char *out, int base) {
    /* Assumes that "out" has enough room. DESTRUCTIVE TO BIGI, so copy */
    /* if you care about the value */
    /* Only really works for non-negative values */
    int i = 0;
    uint8_t swp;
    int j;

    if ((base < 2) || (base > 36)) {
        return NULL;
    }

    if (is_zero(bigi_data, bigi_size)) {
        out[0] = '0';
        out[1] = '\0';
        return out;
    }

    while (!is_zero(bigi_data, bigi_size)) {
        out[i++] = digits[bigdivmod(bigi_data, bigi_size, base)];
    }
    out[i] = 0;
    for (j = 0; j < i/2; j++) {
        swp = out[i - 1 - j];
        out[i - 1 - j] = out[j];
        out[j] = swp;
    }

    return out;
}

int main(int argc, char *argv[]) {
    uint8_t test_data[] = { 0xd5, 0x3c, 0xeb, 0x9d, 0x32, 0xc6, 0xca, 0x06 };
    int test_data_len = sizeof(test_data);
    char *p;

    /* Times 3 because we can use three digits to represent 256. If changing */
    /* the base below from "10", change this factor. */
    p = malloc(3*test_data_len + 1);

    printf("Test data works out to %s\n",
           bigitoa(test_data, test_data_len, p, 10));

    return 0;
}

关于c - c中任意精度数字到ascii,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/46758802/

相关文章:

algorithm - 有效地构造一个方阵,每行都有唯一的数字

c - 指针数组中的未初始化或 NULL 指针

c - 从C中的结尾访问数组?

python - 如何以图形方式编辑数学函数的图形(使用 python)?

r - 将 mpfr 对象列表折叠成单个 mpfr 向量

floating-point - 哪些编程语言具有任意精度的浮点文字?

ruby - Ruby 的任意精度算术

c - 如何通过管道将 C 中定义的变量传递给 Gnuplot?

c - 在 C 中获得大约 20-30 位的精度

c++ - 如何找到硬件算法完全支持的最大整数?