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 шт):

Автор решения: IR42

Литералы справа от = в 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
→ Ссылка
Автор решения: KoVadim

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

маленький суффикс в конце и все готово. Теперь типы с двух сторон совместимы, можно присваивать.

→ Ссылка