Почему при перемножении переменных разных типов получаются разные ответы?
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 шт):
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;
...