【问题标题】:How to store store the value 10^20 in C?如何将值 10^20 存储在 C 中?
【发布时间】:2013-08-10 19:34:51
【问题描述】:

我想将两个尺寸相乘10^10,得到的尺寸是10^20,即2^66

我想将该数字存储在 C 中的标准数据类型中。我宁愿不使用“GNU MP Bignum 库”。

为什么下面的 C 程序不能正确保存数字?

#include<stdio.h>
typedef long long int ull;
int main(){

    ull n1 = 10000000000LL;
    ull n2 = 10000000000LL;

    printf("%llu",n1*n2);
    return 0;
}

持有这个号码并使用它的最佳方式是什么?

【问题讨论】:

  • 除非你有一台支持超过 64 位的单个整数的机器(我确定它们存在,但我不知道有哪个处理器支持),否则没有解决方案。
  • 如果您不想使用现有的库,则必须推出自己的大整数类。
  • @MatsPetersson 汇编器不是实现您自己的大整数类所必需的。
  • 如果你的编译器支持__uint128_t,它应该适合那个乘法的结果。
  • @James:OP 是否要求“任意大整数乘法”或“略高于 64 位”?解决 OP 的问题是我们正在寻找的,对吧?不解决一些刚刚发生的任意问题也解决了 OP 的问题。

标签: c long-long


【解决方案1】:

将其存储为两个 long long 值。这是一个解决方案的草图:

#include <stdio.h>

typedef unsigned long long ull;

void multiply( ull a, ull b, ull * lo, ull * hi )
{
  ull ah = a >> 32;
  ull bh = b >> 32;
  ull al = a & 0xFFFFFFFF;
  ull bl = b & 0xFFFFFFFF;

  ull mid = ah * bl + al * bh;
  ull albl = al * bl;

  ull imm = mid + ( albl >> 32 );

  *lo = ( mid << 32 ) + albl;
  *hi = ah * bh + ( imm >> 32 );
}

int main()
{
  ull n1 = 10000000000LL;
  ull n2 = 10000000000LL;

  ull lo, hi;

  multiply( n1, n2, &lo, &hi );

  printf( "result in hex is %llx%016llx\n", hi, lo );
  return 0;
}

输出:

result in hex is 56bc75e2d63100000

【讨论】:

  • a = ah * 2^32 + al, b = bh * 2^32 + bl, a * b = ( ah * 2^32 + al ) * (bh * 2^32 + bl) = ... 自己展开括号,你就会明白代码的概念
  • 起初我以为你可能错过了从底部到顶部的进位,但现在我看到它是( imm &gt;&gt; 32 )
  • 如果您是硬编码32%016,为什么不保持一致并使用uint64_t。如果你想要 unsigned long long 替换 32sizeof(ull)*8/2 或 sizeof(ull)*char_bit/2` 等。
【解决方案2】:

在 64 位架构上,long long 最多持有 2^63-1。最多 32 位:2^32 -1。如果您需要比这更大的数字,那么您应该重新评估您正在做什么,是否有更好的方法来解决问题。

如果您需要更大的数字,则必须创建自己的库或使用其他人的库:

这里有两个用于处理任意精度数字的库。您可以使用多大的数字的限制取决于您必须持有和计算它们的磁盘空间、内存和处理能力。

GMPMAPM

如果您必须自己滚动,您可以将其存储在整数数组中。一个 64 位整数就是两个 32 位整数。一个 1024 位整数也可以看作是 32 个 32 位整数。创建一个包含整数数组的类,将它们拼接成您需要的任何大小。困难的部分是编写可以加减乘除整数数组的函数。

【讨论】:

    【解决方案3】:

    您可以使用多种策略来实现任意大的数值。

    我个人非常喜欢使用链表。这个想法是将每个数字存储在一个节点中。您需要分别实现加法、减法、乘法和除法函数。

    【讨论】:

    • 使用字符串不是更好吗?
    • 列表和字符串都会非常慢。
    • @MatsPetersson,澄清。这是我个人最喜欢的,所以我用它作为例子。
    • 最好使用 gmp,这是它存在的全部理由。
    • 我并没有故意否决这个答案,但 Stack Overflow 记录了一个否决票(错位点击),所以我做了一个简单的编辑,以便 Stack Overflow 让我撤消投票。
    猜你喜欢
    • 1970-01-01
    • 2018-01-04
    • 2021-06-21
    • 1970-01-01
    • 1970-01-01
    • 2020-03-26
    • 2023-04-04
    • 2020-10-03
    • 2021-05-26
    相关资源
    最近更新 更多