【问题标题】:Division of very large numbers非常大数的除法
【发布时间】:2015-08-29 08:13:34
【问题描述】:

我用 C++ 编写了以下代码:

#include <cmath>
#include <iostream>

using namespace std;

int main()
{
    double sum, containers, n ,c, max_cap, temp;

    unsigned int j = 1;
       cin >> n >> c;
       sum = containers = n;


       for (unsigned int i = 2 ; i <= c; ++i)
       {
           max_cap = i * n;

           if (max_cap - sum > 0)
           {
              temp = ceil((max_cap - sum)/i);
              containers += temp;
              sum += i * temp;
           }
       }

       cout << containers << '\n';
}

当给这个代码的输入是“728 1287644555”时,计算答案大约需要 5 秒,但是当输入大约是“763 3560664427”的三倍时,它不会给很长时间。(我等了大约半小时)可以看出,算法是线性顺序的。因此,大约需要 15 秒。为什么会这样?是因为在第二种情况下输入太大了吗?如果是,那么它对时间的影响如此之大?

【问题讨论】:

  • unsigned double?
  • 这绝对是不是有效的 C++ 源代码,不仅因为unsigned double 还因为continue 退出了循环。你能提供一个有效的变体吗?
  • 除了已经提出的其他问题外,您的问题可能涉及有效unsigned ints 的范围(根据您引用的数字可能是 32 位)和有效doubles(64位)。因此,unsigned int 可能会在循环有机会终止之前溢出并变为0(由于i &lt;= c),因为给定的c 超过了i 在提升为两倍之前可以表示的值。因此,如果c &gt;= UINT_MAX 循环将无限期地继续旋转。
  • 输出例如i 在循环中的值以获得洞察力。此外,您绝对必须学习如何使用调试器,它允许您单步执行代码并检查变量。

标签: c++ time-complexity computation


【解决方案1】:

我的猜测是无符号整数溢出。

       for (unsigned int i = 2 ; i <= c; ++i)

i 增加直到 > c,但 c 是双精度数,而 i 是无符号整数。它达到最大值 (UINT_MAX) 并在达到 c 的值之前回绕到 0。

即1287644555 小于UINT_MAX,所以它完成了。但是 3560664427 大于UINT_MAX,所以它永远循环。这只会引发你在什么奇怪的架构上运行它的问题:)

在我自己的机器上 (UINT_MAX = 4294967295) 处理第一个输入需要 16 秒,而第二个需要 43.5 秒,这几乎是您所期望的。

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-12-06
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2011-01-01
    相关资源
    最近更新 更多