我在c中有一系列未签名的字符我试图在10号基础上打印,但我被卡住了。我认为这将在代码中得到更好的解释,因此,给出:
unsigned char n[3];
char[0] = 1;
char[1] = 2;
char[2] = 3;
我想打印197121。
这对于小型256基数阵列来说是微不足道的。一个可以简单地1 * 256 ^ 0 + 2 * 256 ^ 1 + 3 * 256 ^ 2.
但是,如果我的数组大100字节,那么很快就会出现问题。 C中没有100字节大的整数类型,这就是我将数字存储在unsigned char数组中的原因。
我怎么能在10号基地有效地打印这个号码?
我有点失落。
答案 0 :(得分:8)
使用标准C库没有简单的方法。您要么自己编写函数(不推荐),要么使用GMP之类的外部库。
例如,使用GMP,你可以这样做:
unsigned char n[100]; // number to print
mpz_t num;
mpz_import(num, 100, -1, 1, 0, 0, n); // convert byte array into GMP format
mpz_out_str(stdout, 10, num); // print num to stdout in base 10
mpz_clear(num); // free memory for num
答案 1 :(得分:8)
答案 2 :(得分:3)
我不知道你是否还需要一个解决方案,但我写了一篇关于这个问题的article。它显示了一个非常简单的算法,可用于将任意长数字与基数X转换为相应数量的基数Y.该算法是用Python编写的,但它实际上只有几行,并且不使用任何Python魔法。我也需要这样一个C实现算法,但由于两个原因决定使用Python来描述它。首先,任何理解用伪编程语言编写的算法的人都可以阅读Python,其次,我不允许发布C版本,因为我是为公司做的。看看你会发现这个问题在一般情况下是多么容易解决。 C中的实现应该是直截了当的......
答案 3 :(得分:2)
这是一个可以做你想要的功能:
#include <math.h>
#include <stddef.h> // for size_t
double getval(unsigned char *arr, size_t len)
{
double ret = 0;
size_t cur;
for(cur = 0; cur < len; cur++)
ret += arr[cur] * pow(256, cur);
return ret;
}
这看起来非常易读。只需传递要转换的unsigned char *
数组和大小。请注意,它不会是完美的 - 对于任意精度,我建议查看GNU MP BigNum库,正如已经建议的那样。
作为奖励,我不喜欢您以小端顺序存储您的数字,所以如果您想以big-endian顺序存储base-256数字,这里有一个版本:
#include <stddef.h> // for size_t
double getval_big_endian(unsigned char *arr, size_t len)
{
double ret = 0;
size_t cur;
for(cur = 0; cur < len; cur++)
{
ret *= 256;
ret += arr[cur];
}
return ret;
}
需要考虑的事情。
答案 4 :(得分:0)
提出此建议可能为时已晚或太无关紧要,但是您可以将每个字节存储为两个基本10位数(或一个基数100)而不是一个基数256吗?如果你还没有实现除法,那么这意味着你所拥有的只有加法,减法和乘法;那些不应该太难转换。一旦你完成了它,打印它将是微不足道的。
答案 5 :(得分:0)
由于我对提供的其他答案不满意,因此我决定自己写一个替代解决方案:
#include <stdlib.h>
#define BASE_256 256
char *largenum2str(unsigned char *num, unsigned int len_num)
{
int temp;
char *str, *b_256 = NULL, *cur_num = NULL, *prod = NULL, *prod_term = NULL;
unsigned int i, j, carry = 0, len_str = 1, len_b_256, len_cur_num, len_prod, len_prod_term;
//Get 256 as an array of base-10 chars we'll use later as our second operand of the product
for ((len_b_256 = 0, temp = BASE_256); temp > 0; len_b_256++)
{
b_256 = realloc(b_256, sizeof(char) * (len_b_256 + 1));
b_256[len_b_256] = temp % 10;
temp = temp / 10;
}
//Our first operand (prod) is the last element of our num array, which we'll convert to a base-10 array
for ((len_prod = 0, temp = num[len_num - 1]); temp > 0; len_prod++)
{
prod = realloc(prod, sizeof(*prod) * (len_prod + 1));
prod[len_prod] = temp % 10;
temp = temp / 10;
}
while (len_num > 1) //We'll stay in this loop as long as we still have elements in num to read
{
len_num--; //Decrease the length of num to keep track of the current element
//Convert this element to a base-10 unsigned char array
for ((len_cur_num = 0, temp = num[len_num - 1]); temp > 0; len_cur_num++)
{
cur_num = (char *)realloc(cur_num, sizeof(char) * (len_cur_num + 1));
cur_num[len_cur_num] = temp % 10;
temp = temp / 10;
}
//Multiply prod by 256 and save that as prod_term
len_prod_term = 0;
prod_term = NULL;
for (i = 0; i < len_b_256; i++)
{ //Repeat this loop 3 times, one for each element in {6,5,2} (256 as a reversed base-10 unsigned char array)
carry = 0; //Set the carry to 0
prod_term = realloc(prod_term, sizeof(*prod_term) * (len_prod + i)); //Allocate memory to save prod_term
for (j = i; j < (len_prod_term); j++) //If we have digits from the last partial product of the multiplication, add it here
{
prod_term[j] = prod_term[j] + prod[j - i] * b_256[i] + carry;
if (prod_term[j] > 9)
{
carry = prod_term[j] / 10;
prod_term[j] = prod_term[j] % 10;
}
else
{
carry = 0;
}
}
while (j < (len_prod + i)) //No remaining elements of the former prod_term, so take only into account the results of multiplying mult * b_256
{
prod_term[j] = prod[j - i] * b_256[i] + carry;
if (prod_term[j] > 9)
{
carry = prod_term[j] / 10;
prod_term[j] = prod_term[j] % 10;
}
else
{
carry = 0;
}
j++;
}
if (carry) //A carry may be present in the last term. If so, allocate memory to save it and increase the length of prod_term
{
len_prod_term = j + 1;
prod_term = realloc(prod_term, sizeof(*prod_term) * (len_prod_term));
prod_term[j] = carry;
}
else
{
len_prod_term = j;
}
}
free(prod); //We don't need prod anymore, prod will now be prod_term
prod = prod_term;
len_prod = len_prod_term;
//Add prod (formerly prod_term) to our current number of the num array, expressed in a b-10 array
carry = 0;
for (i = 0; i < len_cur_num; i++)
{
prod[i] = prod[i] + cur_num[i] + carry;
if (prod[i] > 9)
{
carry = prod[i] / 10;
prod[i] -= 10;
}
else
{
carry = 0;
}
}
while (carry && (i < len_prod))
{
prod[i] = prod[i] + carry;
if (prod[i] > 9)
{
carry = prod[i] / 10;
prod[i] -= 10;
}
else
{
carry = 0;
}
i++;
}
if (carry)
{
len_prod++;
prod = realloc(prod, sizeof(*prod) * len_prod);
prod[len_prod - 1] = carry;
carry = 0;
}
}
str = malloc(sizeof(char) * (len_prod + 1)); //Allocate memory for the return string
for (i = 0; i < len_prod; i++) //Convert the numeric result to its representation as characters
{
str[len_prod - 1 - i] = prod[i] + '0';
}
str[i] = '\0'; //Terminate our string
free(b_256); //Free memory
free(prod);
free(cur_num);
return str;
}
这一切背后的想法源自简单的数学。对于任何以256为底的数字,其以10为底的表示可以计算为:
num[i]*256^i + num[i-1]*256^(i-1) + (···) + num[2]*256^2 + num[1]*256^1 + num[0]*256^0
扩展为:
(((((num[i])*256 + num[i-1])*256 + (···))*256 + num[2])*256 + num[1])*256 + num[0]
所以我们要做的就是一步一步地将数字数组的每个元素乘以256,然后将下一个元素加到该元素上,依此类推...这样我们就可以得到以10为底的数字