Nano Hash - криптовалюты, майнинг, программирование

Гипотеза Коллатца С++ странный вывод с большими числами

Итак, мне было скучно, и я решил сделать что-то совершенно рандомное, тут я наткнулся на гипотезу Коллатца: начать с любого положительного числа, а если оно четное, то разделить на два. Если нечетное, умножьте на три и прибавьте единицу. Повторяя это, вы закончите под номером один. Поэтому я сделал этот код:

// Гипотеза Коллатца Лукаса Кнука

#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++ для чайников, все в одном"), но я думаю, что это хорошее начало для меня, и оно работает.

Есть только одна маленькая проблема: если я использую большие числа, они останавливаются на единице и правильно определяют нечетные и четные числа, но...

Посмотрите на эту первую часть вывода при вводе «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-битного целого числа. 25.04.2018
  • ага, я тоже так думал, а как увеличить? хД 25.04.2018
  • Вам нужна большая библиотека int. 25.04.2018
  • Или, если вам стало скучно, напишите в качестве упражнения свою собственную большую функциональность int? Это может быть довольно легко сделать, если вы используете базовые 32-битные и 64-битные операции, хотя легче понять и отладить, если вы используете базовые 8-битные и 16-битные операции. 25.04.2018

Ответы:


1

Вы превысили лимит long long целочисленных значений. Первое значение в вашем выводе усекается, чтобы оно было намного меньше вашего ввода, затем, когда вы добираетесь до 4611686018427387903, оно умножается на 3, поскольку оно нечетное. Вот когда он переполняет тип и заменяется отрицательными значениями. Вам потребуется использовать библиотеку BigInteger, например TTMath.

25.04.2018
  • Спасибо, попробую! 25.04.2018
  • Я делаю что-то не так? никаких ошибок не выдает, но при запуске сразу останавливается: 25.04.2018
  • #include ‹iomanip› #include ‹ttmath/ttmath.h›, используя пространство имен std; int main() { ttmath::Int‹1› n; цин ›› н; cout ‹‹ setw(5) ‹‹ n; 25.04.2018
  • @LucasKnook Пожалуйста, опубликуйте свой новый код отдельным вопросом. Нелегко помогать отлаживать с помощью комментариев. (И вы получите гораздо больше людей, которые смотрят на это.) 25.04.2018

  • 2

    В основном, как указывали другие люди, вы не проверяете переполнение. Но я хотел бы отметить другое: ваш код все еще недействителен, поскольку вы не проверяете, попали ли вы в бесконечный цикл, когда последовательность умножения и деления генерирует одни и те же числа, ваше время никогда не закончится.

    Это правильный код с простым обнаружением переполнения:

    #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;
        }
    }
    
    25.04.2018
  • Гипотеза Коллатца — очень простая математическая задача, никто не знает, почему она всегда заканчивается единицей, я только проверяю, достигла ли она еще единицы, она не будет продолжаться вечно, она всегда остановится на 1. 27.04.2018
  • Нет, именно поэтому это называется догадкой, вы должны проверять, не вычисляете ли вы по пути одни и те же числа снова и снова. 27.04.2018
  • Добавлен код для вашей справки, если вы не понимаете, о чем я говорю, ваш фрагмент неверен. Если вы проголосовали против, пожалуйста, верните. 27.04.2018
  • Новые материалы

    Кластеризация: более глубокий взгляд
    Кластеризация — это метод обучения без учителя, в котором мы пытаемся найти группы в наборе данных на основе некоторых известных или неизвестных свойств, которые могут существовать. Независимо от..

    Как написать эффективное резюме
    Предложения по дизайну и макету, чтобы представить себя профессионально Вам не позвонили на собеседование после того, как вы несколько раз подали заявку на работу своей мечты? У вас может..

    Частный метод Python: улучшение инкапсуляции и безопасности
    Введение Python — универсальный и мощный язык программирования, известный своей простотой и удобством использования. Одной из ключевых особенностей, отличающих Python от других языков, является..

    Как я автоматизирую тестирование с помощью Jest
    Шутка для победы, когда дело касается автоматизации тестирования Одной очень важной частью разработки программного обеспечения является автоматизация тестирования, поскольку она создает..

    Работа с векторными символическими архитектурами, часть 4 (искусственный интеллект)
    Hyperseed: неконтролируемое обучение с векторными символическими архитектурами (arXiv) Автор: Евгений Осипов , Сачин Кахавала , Диланта Хапутантри , Тимал Кемпития , Дасвин Де Сильва ,..

    Понимание расстояния Вассерштейна: мощная метрика в машинном обучении
    В обширной области машинного обучения часто возникает необходимость сравнивать и измерять различия между распределениями вероятностей. Традиционные метрики расстояния, такие как евклидово..

    Обеспечение масштабируемости LLM: облачный анализ с помощью AWS Fargate и Copilot
    В динамичной области искусственного интеллекта все большее распространение получают модели больших языков (LLM). Они жизненно важны для различных приложений, таких как интеллектуальные..