GreenBee
GreenBee

Reputation: 3101

Unsigned lexical comparison of ByteArray

I have two byte arrays and I would like to compare them. I have a loop like this (for clarity, its more of a Javaish loop):

for (i in 0..63) {
    if (newArray[i] != oldArray[i]) {
        return newArray[i] < oldArray[i]
    }
}

For example, newArray[0] is 0x93 and oldArray[0] is 0x00. This still returns true (meaning newArray is smaller than oldArray) because it is done as a signed comparison. Is there a way to compare absolute (unsigned) values? Or a collection to compare byte arrays?

Upvotes: 2

Views: 7125

Answers (1)

Naetmul
Naetmul

Reputation: 15552

You can convert signed Byte to unsigned byte value by converting it to a larger data type (like Int, Long) and then [bitwise and] it and 0xFF.

for (i in 0..63) {
    if (newArray[i] != oldArray[i]) {
        return (newArray[i].toInt() and 0xFF) < (oldArray[i].toInt() and 0xFF)
    }
}

You can make an extension function if you use it a lot.

fun Byte.toUnsignedValue(): Int = this.toInt() & 0xFF

for (i in 0..63) {
    if (newArray[i] != oldArray[i]) {
        return newArray[i].toUnsignedValue() < oldArray[i].toUnsignedValue()
    }
}

Unfortunately, there is no bitwise and operation in Byte and Short in low-version Kotlin (or without experimental feature enabled): bitwise & doesn't work with bytes in kotlin

And, JVM have no unsigned data types except char, which is 2-byte unsigned.

Why doesn't Java support unsigned ints?

It's like there is no operator overloading in Java. Kotlin added operator overloads, but adding unsigned data types is more fundamental problem because JVM inherently does not have them.


You can compare two byte arrays without for loop using zip method, but it will create a new List, so it will be slower than the for-loop method.

Upvotes: 4

Related Questions