有没有一种方法可以将基数 2^64 数字转换为字符串形式的 base10 值,或者在不使用大数字库的情况下以 C 或 C++ 标准输出显示它?
Is there a way to convert a base 2^64 number to its base10 value in string form or display it in standard out in C or C++ without using big num libs?
假设我有一个使用 unsigned long
(int64) 数组表示的非常大的数字,我希望看到它的 base10 形式存储在字符串中 and/or 将其显示为标准直接输出,如果不使用 gmp 或 boost 等库,我如何在 C 或 C++ 中执行此操作?我应该知道什么算法或方法?
下面是一个 base2^64 数字示例,其 base10 值在注释中
// base2^64
unsigned long big_num[3] = [77478, 656713, 872];
// base10 = 26364397224300470284329554475476558257587048
我不确定这是否是将另一个数字基数转换为基数 10 的正确方法,但这是我所做的:
为了得到 base10 值 26364397224300470284329554475476558257587048,我总结了 base2^64 数字的所有数字,乘以它的基数并乘以数字的索引。
base10 = ((77478 * ((2^64)^2)) + ((656713 * ((2^64)^1))) + ((872 * ((2 ^64)^0))))
= 26364397224300470284329554475476558257587048
唯一的问题是没有原始数据类型可以容纳这个超大数额...
我只是在想 boost cpp_int
和 gmp
这样的库是否像这样表示它们的数字,如果是,它们如何将其转换为字符串形式的 base10 值或显示 base10 值标准输出?
或者他们是否只使用他们使用的数据类型的一半位,例如 unsigned long
并且可能使用类似 base 10000 的东西?
要得到这个数的小数表示,需要反复将这个数除以10,取余数得到小数位数。这意味着您需要为大数实现长除法,这也需要实现长加减乘法。
大数库给你的代码太多了,所以只用一个。
重复“mod10”数组以找到下一个最低有效的小数位,然后“除以 10”。根据需要重复。
避免unsigned long
编码 64 位值,因为它可能只有 32 位。
如果代码可以使用最宽的类型对数字 而不是 进行编码并使用 uin32_t
,那么重复数组的“mod 10”就是没那么难。
下面的说明性代码仍然需要反转字符串 - 留给 OP。也可能存在其他缺点 - 因此使用大数字库来处理这类事情的优势。
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
// Form reverse decimal string
void convert(char dec[], size_t n, uint32_t b32[]) {
// TBD code to handle 0
while (n > 0 && b32[0] == 0) {
b32++;
n--;
}
while (n > 0) {
unsigned char rem = 0;
// Divide by 10.
for (size_t i = 0; i < n; i++) {
uint64_t sum = rem * (1ULL << 32) + b32[i];
b32[i] = (uint32_t) (sum / 10u);
rem = (unsigned char) (sum % 10u);
}
*dec++ = (char) (rem + '0');
if (b32[0] == 0) {
b32++;
n--;
}
}
*dec = 0;
}
样本
int main() {
// unsigned long big_num[3] = [77478, 656713, 872];
uint32_t big_num[6] = {0, 77478, 0, 656713, 0, 872};
size_t n = sizeof big_num / sizeof big_num[0];
char s[sizeof big_num * 10 + 1];
convert(s, n, big_num);
printf("<%s>\n", s);
// <84078575285567457445592348207400342279346362>
// 26364397224300470284329554475476558257587048
}
假设我有一个使用 unsigned long
(int64) 数组表示的非常大的数字,我希望看到它的 base10 形式存储在字符串中 and/or 将其显示为标准直接输出,如果不使用 gmp 或 boost 等库,我如何在 C 或 C++ 中执行此操作?我应该知道什么算法或方法?
下面是一个 base2^64 数字示例,其 base10 值在注释中
// base2^64
unsigned long big_num[3] = [77478, 656713, 872];
// base10 = 26364397224300470284329554475476558257587048
我不确定这是否是将另一个数字基数转换为基数 10 的正确方法,但这是我所做的:
为了得到 base10 值 26364397224300470284329554475476558257587048,我总结了 base2^64 数字的所有数字,乘以它的基数并乘以数字的索引。
base10 = ((77478 * ((2^64)^2)) + ((656713 * ((2^64)^1))) + ((872 * ((2 ^64)^0)))) = 26364397224300470284329554475476558257587048
唯一的问题是没有原始数据类型可以容纳这个超大数额...
我只是在想 boost cpp_int
和 gmp
这样的库是否像这样表示它们的数字,如果是,它们如何将其转换为字符串形式的 base10 值或显示 base10 值标准输出?
或者他们是否只使用他们使用的数据类型的一半位,例如 unsigned long
并且可能使用类似 base 10000 的东西?
要得到这个数的小数表示,需要反复将这个数除以10,取余数得到小数位数。这意味着您需要为大数实现长除法,这也需要实现长加减乘法。
大数库给你的代码太多了,所以只用一个。
重复“mod10”数组以找到下一个最低有效的小数位,然后“除以 10”。根据需要重复。
避免unsigned long
编码 64 位值,因为它可能只有 32 位。
如果代码可以使用最宽的类型对数字 而不是 进行编码并使用 uin32_t
,那么重复数组的“mod 10”就是没那么难。
下面的说明性代码仍然需要反转字符串 - 留给 OP。也可能存在其他缺点 - 因此使用大数字库来处理这类事情的优势。
#include <stdlib.h>
#include <stdint.h>
#include <stdio.h>
// Form reverse decimal string
void convert(char dec[], size_t n, uint32_t b32[]) {
// TBD code to handle 0
while (n > 0 && b32[0] == 0) {
b32++;
n--;
}
while (n > 0) {
unsigned char rem = 0;
// Divide by 10.
for (size_t i = 0; i < n; i++) {
uint64_t sum = rem * (1ULL << 32) + b32[i];
b32[i] = (uint32_t) (sum / 10u);
rem = (unsigned char) (sum % 10u);
}
*dec++ = (char) (rem + '0');
if (b32[0] == 0) {
b32++;
n--;
}
}
*dec = 0;
}
样本
int main() {
// unsigned long big_num[3] = [77478, 656713, 872];
uint32_t big_num[6] = {0, 77478, 0, 656713, 0, 872};
size_t n = sizeof big_num / sizeof big_num[0];
char s[sizeof big_num * 10 + 1];
convert(s, n, big_num);
printf("<%s>\n", s);
// <84078575285567457445592348207400342279346362>
// 26364397224300470284329554475476558257587048
}