Collat​​z猜想c ++奇怪的输出大数字

时间:2018-04-25 17:23:27

标签: c++ output long-integer collatz

所以,我很无聊,并且决定做一些完全随机的事情,然后我遇到了一个关于任何正数的猜测:如果它是偶数,那就是两个。如果是奇数,则乘以3并加1。重复此操作时,您将以第一名结束。所以我制作了这段代码:

// Lucas Knook的Collat​​z猜想

#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课程,我即将获得&#34; C ++ for dummies all-in-one&#34; book),但我认为这是一个良好的开端我,它的确有效。

只有一个小问题:如果我使用大数字,它确实停在一个,并得到奇数甚至正确,但......

进入时查看输出的第一部分 &#34; 1000000000000000000000000&#34; :

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
嗯,这有点奇怪,不是吗? (不要看断线,它是完美堆叠的,它只是没有显示在这里,因为我复制了输出)

有人可以解释一下为什么会发生这种情况以及如何解决这个问题吗?

2 个答案:

答案 0 :(得分:1)

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

答案 1 :(得分:-1)

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

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

#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;
    }
}