Kotlin's Long.MIN_VALUE == -9223372036854775808, but when I write:
val minT: Long = -9223372036854775808L //Long.MIN_VALUE
IDEA say it was wrong.
Dmitry Jemerov told me this because the - sign in Kotlin is not part of the constant but rather the unary minus operator applied to the constant value, and 9223372036854775808L is one larger than the maximum possible positive value for the Long type.
But now, why Int is right :
val minI: Int = -2147483648 //Int.MIN_VALUE
Look here:
I believe they bound like that value may need to fall within -9223372036854775808 to 9223372036854775808 because of Long.
Related
I start with a list of integers from 1 to 1000 in listOfRandoms.
I would like to left join on random from the createDatabase list.
I am currently using a find{} statement within a loop to do this but feel like this is too heavy. Is there not a better (quicker) way to achieve same result?
Psuedo Code
data class DatabaseRow(
val refKey: Int,
val random: Int
)
fun main() {
val createDatabase = (1..1000).map { i -> DatabaseRow(i, Random()) }
val listOfRandoms = (1..1000).map { j ->
val lookup = createDatabase.find { it.refKey == j }
lookup.random
}
}
As mentioned in comments, the question seems to be mixing up database and programming ideas, which isn't helping.
And it's not entirely clear which parts of the code are needed, and which can be replaced. I'm assuming that you already have the createDatabase list, but that listOfRandoms is open to improvement.
The ‘pseudo’ code compiles fine except that:
You don't give an import for Random(), but none of the likely ones return an Int. I'm going to assume that should be kotlin.random.Random.nextInt().
And because lookup is nullable, you can't simply call lookup.random; a quick fix is lookup!!.random, but it would be safer to handle the null case properly with e.g. lookup?.random ?: -1. (That's irrelevant, though, given the assumption above.)
I think the general solution is to create a Map. This can be done very easily from createDatabase, by calling associate():
val map = createDatabase.associate{ it.refKey to it.random }
That should take time roughly proportional to the size of the list. Looking up values in the map is then very efficient (approx. constant time):
map[someKey]
In this case, that takes rather more memory than needed, because both keys and values are integers and will be boxed (stored as separate objects on the heap). Also, most maps use a hash table, which takes some memory.
Since the key is (according to comments) “an ascending list starting from a random number, like 18123..19123”, in this particular case it can instead be stored in an IntArray without any boxing. As you say, array indexes start from 0, so using the key directly would need a huge array and use only the last few cells — but if you know the start key, you could simply subtract that from the array index each time.
Creating such an array would be a bit more complex, for example:
val minKey = createDatabase.minOf{ it.refKey }
val maxKey = createDatabase.maxOf{ it.refKey }
val array = IntArray(maxKey - minKey + 1)
for (row in createDatabase)
array[row.refKey - minKey] = row.random
You'd then access values with:
array[someKey - minKey]
…which is also constant-time.
Some caveats with this approach:
If createDatabase is empty, then minOf() will throw a NoSuchElementException.
If it has ‘holes’, omitting some keys inside that range, then the array will hold its default value of 0 — you can change that by using the alternative IntArray constructor which also takes a lambda giving the initial value.)
Trying to look up a value outside that range will give an ArrayIndexOutOfBoundsException.
Whether it's worth the extra complexity to save a bit of memory will depend on things like the size of the ‘database’, and how long it's in memory for; I wouldn't add that complexity unless you have good reason to think memory usage will be an issue.
I have
var x: Int
var invert: Boolean
and I need the value of the expression
if (invert) -x else x
Is there any more succinct way to write that expression in Kotlin?
There is no shorter expression using only the stdlib to my knowledge.
This is pretty clear, though. Using custom functions to make it shorter is possible, but it would only obscure the meaning IMO.
It's hard to tell which approach might be best without seeing more of the code, but one option is an extension function. For example:
fun Int.negateIf(condition: Boolean) = if (condition) -this else this
(I'm using the term ‘negate’ here, as that's less ambiguous: when dealing with numbers, I think ‘inverse’ more often refers to a multiplicative inverse, i.e. reciprocal.)
You could then use:
x.negateIf(invert)
I think that makes the meaning very clear, and saves a few characters. (The saving is greater if x is a long name or an expression, of course.)
If invert didn't change (e.g. if it were a val), another option would be to derive a multiplier from it, e.g.:
val multiplier = if (invert) -1 else 1
Then you could simply multiply by that:
x * multiplier
That's even shorter, though a little less clear; if you did that, it would be worth adding a comment to explain it.
(BTW, whichever approach you use, there's an extremely rare corner case here: no positive Int has the same magnitude as Int.MIN_VALUE (-2147483648), so you can't negate that one value. Either way, you'll get that same number back. There's no easy way around that, but it's worth being aware of.)
You could create a local extension function.
Local functions are helpful when you want to reduce some repetitive code and you want to access a local variable (in this case, the invert boolean).
Local functions are particularly useful when paired with extension functions, as extension functions only have one 'receiver' - so it would be difficult, or repetitive, to access invert if invert() wasn't a local function.
fun main() {
val x = 1
val y = 2
val z = 3
var invert = false
// this local function can still access 'invert'
fun Int.invert(): Int = if (invert) -this else this
println("invert = false -> (${x.invert()}, ${y.invert()}, ${z.invert()})")
invert = true
println("invert = true -> (${x.invert()}, ${y.invert()}, ${z.invert()})")
}
invert = false -> (1, 2, 3)
invert = true -> (-1, -2, -3)
I'm working on my toy project with Kotlin.
While writing code, I feel that those codes are somewhat duplicated and not clean.
val a: Int = 1
val a_D: BigDecimal = a.toBigDecimal()
val b_D: BigDecimal = a.toBigDecimal()
So, is there any way to avoid those duplication(something like toBigDecimal()) using elegant way?
If you are bothered about having to create the BigDecimal over two lines, BigDecimal has constructors that take Int that you can call directly:
val bigDecimalInt = BigDecimal(1)
This is fine for integer values, BUT for floating-point values like Double the constructor and toBigDecimal actually behave differently. The constructor creates a BigDecimal value of the Double value passed in, which will be "incorrect" if that value is not exactly representable in floating-point arithmetic. toBigDecimal converts the value to a String and then uses that which gives the "correct" value
val doubleNum:Double = 0.1
println(doubleNum.toBigDecimal()) // prints 0.1
val bigDecimal:BigDecimal = BigDecimal(0.1)
println(bigDecimal) // prints 0.1000000000000000055511151231257827021181583404541015625
If none of that makes sense, you probably need to read about Floating Point Arithmetic, this is a common problem affecting all/most programming languages
So toBigDecimal is a safer option
(123L).toInt() produces 123 but Long.MAX_VALUE.toInt() produces -1. Clearly this is not correct. Without having to write a lot of boilerplate code, is there a way to get Kotlin to throw an exception when a value is out of range/bounds for the target type?
TL;DR you can make a custom extension function that checks if the value is between Int.MIN_VALUE and Int.MAX_VALUE
fun Long.toIntThrowing() : Int {
if (this < Int.MIN_VALUE || this > Int.MAX_VALUE) {
throw RuntimeException()
}
return this.toInt()
}
The "weird" behavior you are observing is happening, because in Kotlin, Long is represented as a 64 bit signed integer, while Int is represented as a 32 bit signed integer.
While 123L is easily representable by a 32 bit integer, Long.MAX_VALUE will overflow the Integer (almost) twice, resulting in the behavior you are observing.
I believe the example below will illustrate it better:
println((2147483647L).toInt()) // the max 32 bit signed int
println((2147483648L).toInt()) // 1 more overflows it to the min (negative) 32 bit signed int
println((2147483649L).toInt()) // 2 more...
println((Long.MAX_VALUE - 1).toInt())
println((Long.MAX_VALUE).toInt())
results in :
2147483647
-2147483648
-2147483647
-2
-1
From: https://discuss.kotlinlang.org/t/checked-and-unsigned-integer-operations/529/2
Exceptions on arithmetic overflow: this will likely make arithmetics significantly slower, and we don’t see how to avoid it without changes to the JVM, nor are we ready to accept the slowdown
If you are running on the JVM you may use Math.toIntExact:
Returns the value of the long argument; throwing an exception if the value overflows an int.
There doesn't seem to be a pure Kotlin way, but at least you can nicely wrap it:
fun Long.toIntExact() = Math.toIntExact(this)
I'm investigating kotlin using decompilation to java code.
I've found one interesting nuance and can't understand how it is implemented.
Here's the kotlin code:
val result = 50 in 1..100
I'm using intelij idea decompilation to look for the equivalent of java code and here's what we have:
public final class Test14Kt {
private static final boolean result = true;
public static final boolean getResult() {
return result;
}
}
So as i understand it, kotlinc somehow knows that the element is in range and saves true to result variable on the stage of compilation.
It's cool. But how is it achieved?
This is very simple constant folding:
Terms in constant expressions are typically simple literals, such as the integer literal 2, but they may also be variables whose values are known at compile time. Consider the statement:
i = 320 * 200 * 32;
Most modern compilers would not actually generate two multiply instructions and a store for this statement. Instead, they identify constructs such as these and substitute the computed values at compile time (in this case, 2,048,000). The resulting code would load the computed value and store it rather than loading and multiplying several values.
Constant folding can even use arithmetic identities. When x is an integer type, the value of 0 * x is zero even if the compiler does not know the value of x.
Here,
50 in 1..100 ==
1 <= 50 && 50 <= 100 ==
true && true ==
true