Kotlin проблема с числом -2147483648 (0x80000000) при определении Int
Требуется на Kotlin применить к Int маску с поднятым 64 битом. Ппроблема в том, что в Kotlin положить такое число в Int в двоичном или HEX представлении не получается, а при помощи прямых битовых сдвигов или десятичного значения (-2147483648) получается. На Java эти значения заходят в Int без проблем любым способом. ПОЧЕМУ может кто объяснить?
// Kotlin
var a: Int = 0b10000000_00000000_00000000_00000000 //не принимает Kotlin: The integer literal does not conform to the expected type Int
var b: UInt = 0b10000000_00000000_00000000_00000000 //The integer literal does not conform to the expected type UInt
var c: Int = 0x80000000 // не принимает Kotlin: The integer literal does not conform to the expected type Int
var d: Int = -2147483648 // заходит, ошибки нет, получаем нужное значение 0b10000000_00000000_00000000_00000000
var e: Int = 1 shl 31 //принимает и получаем нужное значение 0b10000000_00000000_00000000_00000000
делаем тоже самое на Java:
// Java принимает без проблем
int a = 0b10000000_00000000_00000000_00000000; // работает
int b = 0x80000000; // тоже работает
Документация (думал может в Int какие-то различия - так нет)
Kotlin
Int 32 -2147483648 2147483647
Java
int 32 -2147483648 2147483647
З.Ы. Хочу понять почему не работает, костыли как видите уже сам напридумывал.
Ответы (2 шт):
Литералы справа от = в a, b, c компилятор воспринимает как Long 2147483648 (одинаковое представление с Int -2147483648, если не считать старшие нули), что выходит за пределы Int, при этом в Kotlin нет неявного преобразования типов.
Как и с 2147483648 в d, нужно добавить -
var a: Int = -0b10000000_00000000_00000000_00000000
var c: Int = -0x80000000
В случае b нужно добавить суффикс u в конце числа.
var b: UInt = 0b10000000_00000000_00000000_00000000u
int в java и в котлин - 32битный. Как в таком числе выставить 64бит - да никак. Нельзя впихнуть то, что не впихивается. Используйте тип Long - там будет 64бита.
Посмотрел на код - там 32битные маски (числа). Значит с 64 битами скорее всего ошибка произошла. Ок, прочитаем вопрос так, как будто там написано 32, где видно число 64.
Java - это язык, который пытался исправить проблемы с/с++ (да да, будучи сам на нем написанным) и решил, что лучше иметь только знаковые типы, а беззнаковые выбросить.
Но тогда было принято немного игнорировать ошибки при разных переполнениях (видимо люди лучше понимали, как работают битики на низком уровне). А вот в Котлин решили исправить обе ошибки - и беззнаковые типы ввести, и с переполнениями разобраться.
Итак, в знаковых типах старший бит - это обычно знаковый бит. 1 значит минус.
Посмотрим на примеры
var a: Int = 0b10000000_00000000_00000000_00000000
тут все очевидно. Число, записанное слева чуточку больше, чем верхняя граница Int, компилятор, что бы пользователь не поранился, просто не дает ему стрельнуть в ногу.
Третий пример
var c: Int = 0x80000000
а это то же самое. Абсолютно. Просто число записано не в двоичной системе, а в 16-ричной. И объяснение то же самое.
Теперь вернемся к второму примеру.
var b: UInt = 0b10000000_00000000_00000000_00000000
тут вроде выглядит нормально, но есть одна проблема - число, записанное слева - это целое со знаком (тип по умолчанию), а котлин не хочет так, ему нужно четко. И это легко исправить
var b: UInt = 0b10000000_00000000_00000000_00000000u
маленький суффикс в конце и все готово. Теперь типы с двух сторон совместимы, можно присваивать.