BabyishTank
BabyishTank

Reputation: 1482

Kotlin long literal: The value is out of range

bit mask 0xaaaaaaaaaaaaaaaaL (16a's) is out or range in kotlin. If I have Android Sutdio automatically convert from Java, it translate to -0x5555555555555556L, which is 101010101010101010101010101010101010101010101010101010101010110, it is now only 63 bit and 0110 at the end is off.

0xaaaaaaaaaaaaaaaaL works well in Java. I need an explanation of why it becomes -0x5555555555555556L in kotlin. Another question is how does kotlin represent negative Long? Why the - sign in the front? It is not 2's complement like in Java?

I looked at the doc https://kotlinlang.org/docs/basic-types.html#literal-constants, I know kotlin support Hexadecimals syntax.

I also tried Unsigned Long val mask2: ULong = 0xaaaaaaaaaaaaaaaaL same problem.

Thanks in advance

Upvotes: 5

Views: 3994

Answers (3)

Adam Millerchip
Adam Millerchip

Reputation: 23147

Kotlin doesn't let you create literal values greater than Long.MAX_VALUE, but you can declare an unsigned long and convert it to a long with he same binary value like this:

val long = 0xaaaaaaaaaaaaaaaau.toLong()

Example:

fun main() {
    val long = 0xaaaaaaaaaaaaaaaau.toLong()
    println(long.toString(16))
    println(long.toString(2))
    println(long.toULong().toString(16))
    println(long.toULong().toString(2))
}

Output:

-5555555555555556
-101010101010101010101010101010101010101010101010101010101010110
aaaaaaaaaaaaaaaa
1010101010101010101010101010101010101010101010101010101010101010

Upvotes: 4

Sweeper
Sweeper

Reputation: 275015

The reason why that literal works in Java is because Java's hexadecimal integer literals can represent negative numbers, and 0xaaaaaaaaaaaaaaaaL just so happens to fit 64 bits. From the JLS 3.10.1:

A hexadecimal numeral consists of the leading ASCII characters 0x or 0X followed by one or more ASCII hexadecimal digits interspersed with underscores, and can represent a positive, zero, or negative integer.

It is a compile-time error if a hexadecimal, octal, or binary long literal does not fit in 64 bits.

(Note that decimal literals in Java OTOH can only represent non-negative integers).

So in Java, 0xaaaaaaaaaaaaaaaaL doesn't represent the positive number

12297829382473034410

After all, Long in both languages only has the max value of

9223372036854775807

It instead represents the negative number

-6148914691236517206

You can see that this is the case in Java by printing the number in hex:

long a = 0xaaaaaaaaaaaaaaaaL;
System.out.println(Long.toString(a, 16));
// -5555555555555556
// this is the same hex you get when you translate to Kotlin!

Kotlin's hexadecimal literals don't represent negative integers, so 0xaaaaaaaaaaaaaaaaL is out of range, because it represents 12297829382473034410, rather than -6148914691236517206.

Upvotes: 3

enzo
enzo

Reputation: 11531

You can use Java's parsing:

val x: Long = java.lang.Long.parseUnsignedLong("aaaaaaaaaaaaaaaa", 16)
println(x)    // Outputs -6148914691236517206

You can look here for some explanation.

Upvotes: 3

Related Questions