Я не понимаю, почему это решение сработало. (Целочисленное переполнение) - PullRequest
2 голосов
/ 05 мая 2020

Извините за плохое название, но я понятия не имел, как его назвать. У меня есть решение некоторых проблем для практики, и я наткнулся на эту. Задача заключалась в том, чтобы написать класс для коробки. Итак, у него были долгота, высота и ширина. Один из способов должен был вернуть объем ящика. Это похоже на его резюме:

#include<bits/stdc++.h>

class Box {
private:
    int l,b,h;
public:
    Box(int L, int B, int H){
        l=L;b=B;h=H;
    }
    int CalculateVolume() {
        return b*l*h;
    } 
};

int main() {
    int l,b,h;
    std::cin << l << b << h;
    Box box(l, b, h);
    std::cout << box.CalculateVolume() << std::endl;
}

Затем, когда пришло время для тестовых случаев, он выдал мне ошибку.

Input: 1039 3749 8473
Output: -1355615565

Итак, я сказал, хорошо, результат слишком велик. Давайте увеличим тип возвращаемого значения

    long long int CalculateVolume() {
        return b*l*h;
    } 
// No changes to the rest

И результат был таким же, поэтому я сказал: «Хорошо, еще больше» и сделал следующее:

    unsigned long long int CalculateVolume() {
        return b*l*h;
    } 
// No changes to the rest
Input: 1039 3749 8473
Output: 18446744072353936051

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

    unsigned long long int CalculateVolume(){
        unsigned long long int volume = b*h*l;
        std::cout << volume << std::endl;
        return volume;
    } 
// No changes to the rest
Input: 1039 3749 8473
Output: 
18446744072353936051
18446744072353936051

Результат меня не удивил. Из последних сил, и я действительно не знаю, откуда взялась эта идея, я сделал следующее:

    unsigned long long int CalculateVolume(){
        unsigned long long int volume = b*h;
        unsigned long long int a = volume * l;
        return a;
    } 
// No changes to the rest

И, к моему удивлению, я получил правильный ответ

Input: 1039 3749 8473
Output: 33004122803

Но я правда не понимаю почему. И, самое главное, следует ли мне делать это в своих программах на случай, если они будут обрабатывать действительно большие числа? Или как мне с этим справиться?

1 Ответ

0 голосов
/ 05 мая 2020

Очень спасибо за помощь. TIL, что если переменные являются целыми числами, не имеет значения, что результат операции присваивается long long int, операция будет выполняться с помощью int maths. Итак, специальное решение c, с которым я работал, потому что b * h по-прежнему было целым числом без проблем, и когда я затем умножил его на l, он уже работал с ними как long int. Это будет окончательное решение:

#include<bits/stdc++.h>

class Box {
private:
    long long int l,b,h;
public:
    Box(int L, int B, int H){
        l=L;b=B;h=H;
    }
    long long int CalculateVolume() {
        return b*l*h;
    } 
};

int main() {
    int l,b,h;
    std::cin >> l >> b >> h;
    Box box(l, b, h);
    std::cout << box.CalculateVolume() << std::endl;
}

Опять же, большое спасибо за вашу помощь

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...