C ++ целочисленное умножение: объясните это поведение - PullRequest
2 голосов
/ 15 апреля 2020

Я написал простую функцию в C ++ для вычисления объема объекта Box, который имеет длину, ширину и высоту. Это часть класса, поэтому l,b,h являются частными членами:

long long CalculateVolume(){
        return l*b*h;
}

Это не работает правильно с большими значениями l,b,h. В моем случае l = 1039, b = 3749, h = 8473. Результат был

-1355615565

Я думал, что это из-за переполнения, поэтому я попытался

unsigned long long CalculateVolume(){
        return l*b*h;
}

, но результат был

18446744072353936051

Наконец, все получилось умножить целые числа на шаги:

long long CalculateVolume(){
        long long result = l;
        result *= b;
        result *= h;
        return result;
}

, что дало правильный результат 33004122803. Я не понимаю, почему это решение работает. Можете ли вы объяснить, что происходит под капотом в каждом из трех случаев? Спасибо!

Ответы [ 2 ]

4 голосов
/ 15 апреля 2020

Если ваши переменные l, b и h равны long long, то поведение обоих фрагментов будет идентичным.

Однако, если переменные равны int с, то в первом фрагменте

return l * b * h;

приведет к переполнению. Преобразование в long long произойдет только тогда, когда результат вернет , что слишком поздно.

В этом фрагменте

long long result = l;
result *= b;           // multiplying 'int' and 'long long' is like multiplying 2 'long long's
result *= h;
return result;

вы только когда-либо умножаете long long с, так что вы не переполняетесь.

Вы можете сделать ваши переменные long long для начала или привести их к переменному перед умножением.

0 голосов
/ 15 апреля 2020

Я думаю, что типы ваших 3 переменных: l, b и h ответственны за неправильное поведение, если они являются целыми значениями, их умножение также является целым числом. Таким образом, вы должны привести их к длинным длинным или неподписанным задолго до умножения. Или, как вы делали в последнем фрагменте кода, вы можете привести только один из них, и тогда умножение будет иметь самый большой тип между факторами (в данном случае это long long)

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