【问题标题】:Collatz Conjecture c++ weird output with big numbersCollat​​z Conjecture c++ 奇怪的输出与大数字
【发布时间】:2018-04-25 17:23:26
【问题描述】:

所以,我很无聊,决定做一些完全随机的事情,然后我遇到了 collat​​z 猜想:从任何正数开始,如果是偶数,则除以 2。如果是奇数,则乘以三并加一。重复此操作时,您将以第一名结束。所以我做了这个代码:

//卢卡斯·诺克的科拉茨猜想

#include <iostream>
#include <iomanip>
using namespace std;

int main() {
    long long n;
    cin >> n;
    cout << setw(5) << n;

    while(true){
        if(n % 2 == 0 && n != 1){
            //is even
            cout << " E" << endl;
            n /=2;
            cout << setw(5) << n;
        }
        else if(n != 1){
            //is odd
            cout << " O" << endl;
            n = n * 3 + 1;
            cout << setw(5) << n;
        }
        else break;
    }
    cout << " O" << endl << endl << "end loop";
    return 0;
}

我还在学习 c++(我刚刚完成了 sololearn 课程,我即将获得“C++ for dummies all-in-one”一书),但我认为这对我来说是一个好的开始,而且它很有效.

只有一个小问题:如果我使用大数字,它确实会停在 1 处,并得到奇数和偶数,但是......

输入时查看输出的第一部分 “1000000000000000000000000”:

9223372036854775807 O
9223372036854775806 E
4611686018427387903 O
-4611686018427387906 E
-2305843009213693953 O
-6917529027641081858 E
-3458764513820540929 O
8070450532247928830 E
4035225266123964415 O
-6341068275337658370 E
-3170534137668829185 O
8935141660703064062 E
4467570830351532031 O
-5044031582654955522 E
-2522015791327477761 O
-7566047373982433282 E
-3783023686991216641 O
7097673012735901694 E
3548836506367950847 O
-7800234554605699074 E

嗯,这有点奇怪,不是吗? (别看换行符,叠得很完美,只是这里没有显示,因为我复制了输出)

谁能解释一下为什么会发生这种情况以及如何解决它?

【问题讨论】:

  • 我认为你已经超过了 64 位整数的最大值。
  • 是的,我也是这么想的,有什么办法让它变大吗? xD
  • 你需要一个大的 int 库。
  • 或者如果你坐下来很无聊,写你自己的大 int 函数作为练习?如果你使用基本的 32 位和 64 位操作,这很容易做到,但如果使用基本的 8 位和 16 位操作,则更容易理解和调试

标签: c++ output long-integer collatz


【解决方案1】:

您已超出long long 整数值的限制。输出中的第一个值被截断为比输入小得多,然后当您到达4611686018427387903 时,它乘以 3,因为它不是偶数。那是它溢出类型并环绕成负值的时候。您需要使用 BigInteger 库,例如 TTMath

【讨论】:

  • 我做错什么了吗?它没有给出任何错误,但是当我启动它时,它会立即停止:
  • #include #include using namespace std; int main() { ttmath::Int n;辛 >> n; cout
  • @LucasKnook 请将您的新代码作为单独的问题发布。通过 cmets 帮助调试并不容易。 (你会得到更多的人关注。)
【解决方案2】:

基本上正如其他人指出的那样,您不检查溢出。但我想指出不同的事情,你的代码仍然无效,因为你没有检查你是否进入了无限循环,当乘法和除法序列生成相同的数字时,你的 while 永远不会结束。

这是带有简单溢出检测的正确代码:

#include <iostream>
#include <unordered_set>

bool colatazConjecture(int n) {
    std::unordered_set<int> localComputed;
    int newN = 0;

    while (n != 1) {
        if (!localComputed.emplace(n).second) {
            throw "Cycle detected";
        }

        newN = n;
        if (n & 0x1) {
            newN = 3*n + 1;
            if (newN <= n) {
                throw std::overflow_error("Overflow for " + std::to_string(newN));
            }
        } else {
            newN >>= 1;
        }
        n = newN;
    }
}

【讨论】:

  • 科拉茨猜想是一道很简单的数学题,没有人知道为什么它总是以1结束,我只检查它是否达到了第一,它不会永远持续下去,它会一直停在1.
  • 不,这就是为什么它被称为“猜想”,你必须检查你是否在路上一遍又一遍地计算相同的数字。
  • 添加代码供您参考,如果您不知道我在说什么,您的sn-p 不正确。如果您投了反对票,请回复。
猜你喜欢
  • 2021-12-14
  • 1970-01-01
  • 2019-01-21
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2021-12-03
相关资源
最近更新 更多