Title
n

neworldlt

12/08/2021, 5:25 PM
What is an idiomatic way of calculating the power of two for integers?
j

Joffrey

12/08/2021, 7:36 PM
You mean 2^n ? You can shift to the left I guess, using
``1 shl n``
d

Daniel

12/08/2021, 9:01 PM
If you care about the readers of your code please don't use bit shifts if you don't have to 😄 I think good old java.lang.Math.pow is a good bet. Or you can build an an extension function which uses the already existing https://kotlinlang.org/api/latest/jvm/stdlib/kotlin.math/pow.html#kotlin.math\$pow(kotlin.Double,%20kotlin.Double) (I wonder why they did not build an extension for Int)
j

Joffrey

12/08/2021, 9:17 PM
If you make an extension function for 2^n, you may as well use the bit shift inside :D but if you don't I would argue the extra conversions between doubles and ints might actually make it on par in terms of readability
``1 shl n // 2^n``
than
``Math.pow(2.0, n.toDouble()).toInt()``
4
s

Stephan Schroeder

12/09/2021, 7:49 AM
better add an argument range check
``````fun twoPow(exponent: Int): Int {
require(exponent in 0..32) {"exponent must be in 0-31 but was \$exponent"}
return 1 shl n // 2^n
}``````
``val x = twoPow(5)``
is hopefully even easier to read. I didn't make it an extension function because i wanted to retain the order of 2 and 5.
n

neworldlt

12/09/2021, 8:01 AM
``Math.pow()``
can't guarantee the precision of what I need for bitwise operations.
``shl``
does not look idiomatic either, because it is hard to read. I would say
``twoPow(x)``
is winner here, however, it does not look idiomatic because it is not a part of stdlib, but maybe should
I wonder why they did not build an extension for Int
I guess it is because of precision. Double does not need that much of it.
m

Michael de Kaste

12/09/2021, 1:49 PM
for any arbritary int, I'd rather use
``fun Int.pow(power: Int) = toBigInteger().pow(power)``
powers can quite easily grow outside of the scope of an Int, so you have to decide what to do if your int gets out of range for its size. If you feel like you don't care, you can just do the .toInt() as part of it again.
j

Joffrey

12/09/2021, 2:05 PM
@neworldlt the short answer is that there isn't really any idiomatic way because there isn't anything in the stdlib for this use case at the moment (at least to my knowledge). So now you have to pick your non-idiomatic poison 🙂 Most options suggested here seem valid to me at least in some contexts. • If you're dealing with powers of 2 exclusively in this piece of code, I would go for the bit shift. It's short enough so it's easy to lookup for beginners that don't understand it, and a quick
``// 2^n``
comment is a very short and clear way to explain the intent of it. But if it's not enough you can also extract it to a function like @Stephan Schroeder suggested. Also, incidentally (if it matters) I believe its performance will outweigh any other options in this case. • If the base 2 was just incidental here and you're in fact using other bases in the same area of code, a custom extension for
``Int.pow(Int)``
as @Michael de Kaste suggested would be my choice. The way you implement it is up to you (going through
``Double``
or
``BigInteger``
) but likely
``BigInteger``
will be safer regarding overflows
👍 1