【问题标题】:Allocating large memory in C (Project Euler Prob)在 C 中分配大内存(Project Euler Prob)
【发布时间】:2013-03-10 17:14:23
【问题描述】:

我试图在项目 euler click here 上使用 C 来解决问题 这是代码。它适用于 10 个值,但对于 1000 个值,它会给出错误的输出。我注意到它在 32 之前给出了正确的输出。我认为我超出了内存或其他东西。这么大的数组如何分配内存?

#include <stdio.h>
int main() { 
    int a[10], i, sum=1, b=0;

    for(i = 1; i < 10; i++) { 
        a[0] = 1;
        a[i] = sum + a[i-1];
        sum = sum + a[i-1];
    }

    for(int j = 1;j > 0; j++) {
        b = b + sum%10;

        if(sum<10)
            break;

        sum = sum/10;
     }

     printf("%d\n",b);

     return 0;
 }

【问题讨论】:

  • int 类型无法容纳所需的值。您需要用不同的方法解决问题(提示:使用char 的数组将数字表示为字符串)。
  • 如果我的复制/粘贴能力很强,2 的 1000 次方是 10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069###(最后 3 位被删减)
  • 只使用 Wolfram Alpha,哈哈。
  • 遗憾的是,这甚至不适合 uint64_t。现在有两种方法,要么使用 GMP,要么有争议的“使用 Python”,因为默认情况下它的标准库中有大量数据。或者,当然,自己动手:P
  • 检查可以打印出来的 2 的幂。看看每个数字的位置,看看你能不能推断出一个模式。看数字的总和。那里有模式吗?看看你从 2**i 到 2**(i+1) 会发生什么。那里有什么模式吗?

标签: c arrays math memory-management


【解决方案1】:

您可以尝试将 21000 计算为 80 位 long double,然后使用 sprintf 将其转换为字符串,然后对该字符串的数字求和。

为什么会这样:

浮点类型将数字存储为尾数乘以指数。指数始终是 2 的幂,尾数可以是 1。对于 long double,指数最大可以是 216383printf 和朋友们,在现代实现中,将正确打印出浮点数的数字。

代码:

int main() {
  char buf[1024]; int ans = 0;
  sprintf(buf, "%.0f", 0x1.0p1000);
  for (int i = 0; buf[i]; i++) ans += buf[i] - '0';
  printf("%i\n", ans);
}

【讨论】:

  • 不要用整型表示。 (我从未说过你应该这样做。)就像我说的那样,将其表示为 long double。然后您可以使用sprintf 将其精确计算为字符串,就像我说的那样。计算 21000long double 完全一样是微不足道的。
  • 但这只是二进制表示。它是 2^1000,但不是十进制数字。
  • 是的,我愿意。你试过编码你在说什么吗?你能得到超过20位数的输出吗?请张贴代码。
  • 是的。它有效。你觉得我是怎么解决这个问题的?你试过了吗?
  • +1 简直太棒了。不过,您可以为怀疑者发布代码。
【解决方案2】:

我注意到它在 32 点之前给出了正确的输出

也就是说,因为您使用的整数类型有 32 位。它根本无法容纳更大的数字。你不能用传统的方式解决它。

以下是我的建议:首先让我们估计一下这个数字有多少位数。每当一个数字在十进制中得到 10 倍时,就需要写入一个新数字。所以十进制数的位数由 ceil(log10(n)) 给出。所以对于 2^1000,你需要 ceil(log10(2^1000)) 数字,但这只是 ceil(1000*log10(2)) = 302,所以你需要 302 个十进制数字来写下来。

这给出了下一个想法:用 302 位数字写下数字 1,即 301 次 '0' 和一个字符串中的 '1'。然后将字符串加倍 1000 次,就像在小学时一样将其添加到自身中,携带溢出的数字。


编辑 我想我应该指出,遇到的问题是这个 Project Euler 问题的重点。欧拉计划问题都有一个共同点,即您无法使用幼稚的编程方法来解决它们。你必须发挥创造力来解决它们!

【讨论】:

    猜你喜欢
    • 2016-12-06
    • 1970-01-01
    • 1970-01-01
    • 2019-02-03
    • 2017-11-14
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2014-05-22
    相关资源
    最近更新 更多