【问题标题】:Algorithm for printing decimal value of a huge(over 128bits) binary number?用于打印巨大(超过 128 位)二进制数的十进制值的算法?
【发布时间】:2019-04-23 10:23:28
【问题描述】:

TLDR,在底部:)

简介: 我正在创建一个用于处理大量数字的基本算术库(加法,减法,...)。我面临的问题之一是将这些巨大的二进制数打印成十进制。

我有一个巨大的二进制数存储在一个 uint64_t 数组中。例如

uint64_t a[64] = {0};

现在,目标是将控制台/文件中的 64*64 位二进制数打印为十进制值。

初步工作: 为了详细说明问题,我想描述一下我是如何打印十六进制值的。

int i;
int s = 1;
a[1] = (uint64_t)0xFF;
for(i = s; i>= 0; i--)
{
    printf("0x%08llX, ", a[i]);
}

输出:

0x000000FF, 0x00000000, 

与打印 OCT 值类似,我可以从 a[64] 中获取 LSB 3 位,打印这些位的十进制等效值,3 位右移 a[64] 的所有位并不断重复直到 a[ 的所有值64] 已打印。 (以相反的顺序打印以保留右侧的第一个 Oct 数字)

我可以通过重复这个单位算法来打印无限大小的二进制的十六进制和八进制值,但是我找不到/开发一个十进制的值,我可以一遍又一遍地重复打印 [64](或其他东西更大)。

我想到的: 我最初的想法是不断减法

max_64 =(uint64)10000000000000000000; //(i.e.10^19)

uint64_t 内 10 的最大倍数,从 a 直到 a 内的值小于 max_64(基本上相当于 rem_64 = a%max_64 )并使用

打印 rem_64 值
printf("%019llu",rem_64);

这是数字a 的第一个 19 位十进制数字。

然后做一个类似于(不是代码)的算术运算:

a = a/max_64; /* Integer division(no fractional part) to remove right most 19 dec digits from 'a' */

并不断重复和打印 19 位十进制数字。 (以这样的方式打印,首先找到的 19 位数字在右侧,然后接下来的 19 位数字在其左侧,依此类推......)。

问题是这个过程很长,我不想使用所有这些来打印 dec 值。并且正在寻找一种避免使用这些耗时巨大的算术运算的过程。

我相信必须有一种方法可以通过重复算法来打印大尺寸(类似于如何打印 Hex 和 Oct ),我希望有人能指出我正确的方向。

我的图书馆能做什么(到目前为止):

  • 添加(使用全加器)
  • Sub(使用全减法器)
  • 比较(通过比较数组大小和比较数组元素)
  • Div(整数除法,无小数部分)
  • 模数 (%)
  • 乘法(基本上是多次相加:()

如果需要,我会为其他操作编写代码,但如果可能的话,我想实现独立于库的打印功能。

考虑这样的问题: 您已获得 n 位 (1

TLDR: 我可以重复用于打印太大和/或未知大小的二进制的十进制值的任何代码、参考或单位算法都会很有帮助。强调算法,即如果有人可以描述我能够实现它的过程,我不需要代码。提前致谢。

【问题讨论】:

  • 最终你将实现除法和取模。这些是您需要转换为十进制的内容。
  • 您是否实现了基本操作(add、sub、div、mod、equal to、greater then 等)?你能展示一下吗? the biggest multiple of 10 inside uint64_t“从 uint64_t 除以 10 的最大倍数的最大余数”怎么样? IE。 a[i] % max_64 会发生什么? The problem is this process is to long - 所以是你写的?然后请出示代码。也许正确的分析、重写、矢量化代码可以更快。
  • @KamilCuk:更新了问题以澄清您的一些问题。不幸的是,共享代码会有点复杂,所以我共享了算法。我可以澄清为什么它需要太长时间,这是因为每个库函数基本上都是蛮力实现,比如使用全加器将每个位添加到 (64*64) 位以添加到这些大数字中,对于 sub、div 也是如此, mul ...我的建议是考虑这样的问题:给你一个 n 位的二进制数 X (1
  • 不管大算术如何,我都在做这个操作(对于初学者来说,当算术还没有完全起作用或测试时)......这可以单独在 8 位算术上完成。只需创建十六进制字符串(正如您已经指出的那样很容易),然后将十六进制字符串转换为 dec,就像这里How do I convert a very long binary number to decimal? 一样。我认为您应该阅读此Fast bignum square computation 这可能会让您很感兴趣...

标签: c algorithm data-conversion


【解决方案1】:

当面临这样的疑问时,考虑到那里有许多 bigint 库,研究它们的代码很有趣。我查看了 Java 的 BigInteger,它有一个 toString 方法,它们做了两件事:

Knuth,Donald,计算机编程的艺术,卷。 2、答案 练习 (4.4) 问题 14.

【讨论】:

  • Schönhage 算法仅适用于 非常大 的数字,例如 ~45000bits +/- 实现,这在大多数情况下并不实用。所以在大多数情况下,Karatsuba 是更好的选择......
  • @Spektre Java 源代码中的注释发现它更快lower thresholds 再说一次,语言和编译器优化很重要,OP 打算使用 C 而不是 Java。
  • 是的,那是 +/-implementation,因为 JAVA 总体上比 C/C++ 慢,所以阈值更低...
猜你喜欢
  • 2019-11-29
  • 2017-05-19
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-02-26
  • 1970-01-01
  • 2016-12-13
  • 2014-11-08
相关资源
最近更新 更多