下面是一个应该工作的方法。请注意,它会破坏性地修改您传递给它的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 = "abcdefghijklmnopqrstuvwxyz";
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;
}
你能举个例子吗?甚至可能是[mcve]? – Yunnosch
基本上,你必须实施长期分工。 –
这取决于您需要在文本和数字之间进行多少转换。如果使用基数'100'而不是'256',则文本输出几乎是微不足道的,但是有一个折衷,因为您的bignum的算术计算需要使用效率较低的'%'而不是'&'来分隔部分总和,产品等 –