Почему при перемножении переменных разных типов получаются разные ответы?

int x = 1000000; // (10 ^ 6)
long res = x * x;
cout << res; // вывод получается неправильным.

long int x = 1000000;
long res = x * x;
cout << res; // теперь же вывод правильный.

Не понимаю, в чем проблема. Ведь в int точно входит 10 ^ 6, а в long 10 ^ 18.


Ответы (2 шт):

Автор решения: Harry
int x = 1000000; // (10 ^ 6)
long res = x * x;

Вычисляется x*x - как произведение двух int, а значит, и результат int. "Втискиваем" 1012 в int, а потом присваиваем long.

Что не так?...

И, кстати, в long далеко не везде входит 1018, это зависит от конкретного компилятора.

→ Ссылка
Автор решения: Павел Ериков

Если вы перемножаете две переменные одного типа, то и результат будет этого типа, но только если размер этих типов не меньше int. Иначе происходит преобразование к int и результат так же возвращен будет в int.

Например:

short x = 32767;
int res = x * x; //short < int => будет перемножение двух int-ов =>
// => и результат будет возвращен типа int
// аналогично будет работать например с unsigned char

Такой процесс преобразования типов называется: "Неявное преобразование типов"

То есть, когда вы пишите:

int x = 1000000;
long res = x * x; //Перемножение int-ов => и результат возвращается int

Т.к. результат возвращается типа int, то происходит переполнение и вот после этого, это значение присваивается long res.

Чтобы исправить эту проблему, нужно один из множителей привести к большему типу, чем int в вашем случае long.

int x = 1000000;
long res = (long)x * x;

Так же стоит сказать про, то что long, как и long long и другие подобные типы данных. На разных компиляторах могут иметь разный размер => и диапазон значений другой.

Лично у меня на Visual Studio 2019 long и int одного размера :)

Можно использовать типы данных, размер которых не изменяется.

Например:

#include <climits>
...
int32_t x = 1000000;
int64_t res = (int64_t)x * x;
...
→ Ссылка