如何在Kotlin中为每种Number类型实现发言权模数? [英] How to implement floor modulo for every Number type in Kotlin?
问题描述
I'm currently learning Kotlin and trying to create an extension (infix) method that works on all number types (Byte
, Long
, Float
, etc.). It should work like Python's %
operator:
4 % 3 == 1 // only this is the same as Java's %
4 % -3 == -2
-4 % 3 == 2
-4 % -3 == -1
...or like Java's Math.floorMod
, but it should also work with Double
or Float
:
-4.3 % 3.2 == 2.1000000000000005
或这些类型的任何可能组合
or with any possible combination of these types
3 % 2.2 == 0.7999999999999998
3L % 2.2f == 0.7999999999999998
以下内容按预期工作,但仅适用于两个Double
或两个Int
:
The following works as intended, but only for two Double
or two Int
:
inline infix fun Double.fmod(other: Double): Number {
return ((this % other) + other) % other
}
inline infix fun Int.fmod(other: Int): Number {
return ((this % other) + other) % other
}
// test
fun main(args: Array<String>) {
println("""
${-4.3 fmod 3.2} == 2.1000000000000005
${4 fmod 3} == 1
${+4 fmod -3} == -2
${-4 fmod 3} == 2
${-4 fmod -3} == -1
""")
}
用Number
替换Int
时,出现以下错误消息:
Replacing Int
with Number
, I get the following error messages:
Error:(21, 18) Unresolved reference. None of the following candidates is applicable because of receiver type mismatch:
@InlineOnly public operator inline fun BigDecimal.mod(other: BigDecimal): BigDecimal defined in kotlin
Error:(21, 27) Public-API inline function cannot access non-public-API 'internal open fun <ERROR FUNCTION>(): [ERROR : <ERROR FUNCTION RETURN TYPE>] defined in root package'
Error:(21, 36) Public-API inline function cannot access non-public-API 'internal open fun <ERROR FUNCTION>(): [ERROR : <ERROR FUNCTION RETURN TYPE>] defined in root package'
如何在不复制粘贴每种类型组合的情况下为每种数字类型实现此目标?
How can I achieve this for every number type without copy-pasting this for every type combination?
推荐答案
唯一合理的选择(也是最快的选择)是为要支持的每对类型定义运算符:
The only reasonable option (also the fastest) is to define the operator for each pair of types you want to support:
infix fun Double.fmod(other: Double) = ((this % other) + other) % other
infix fun Int.fmod(other: Int) = ((this % other) + other) % other
infix fun Double.fmod(other: Int) = ((this % other) + other) % other
infix fun Int.fmod(other: Double) = ((this % other) + other) % other
这样,由编译器(而不是在运行时)决定使用哪种类型.这些函数不是通用的,也不使用继承(读取Number
),这意味着未对值进行装箱(请参见Java基本装箱),这意味着未分配对象.
That way the decision of what type to use is made by the compiler, not at the runtime. Those functions are not generic and do not use inheritance (read Number
), which means that the values are not boxed (see Java primitive boxing), meaning that objects are not allocated.
我强烈建议不要内联这些功能.保留对JVM的次要优化.未分配对象这一事实是这里最大的性能优势.
I strongly do not recommend inlining those functions. Leave minor optimizations to JVM. The fact that objects are not allocated is the biggest performance win here.
P.S功能的数量随着所支持类型的平方而增长.确定要支持所有类型?
P.S The number of functions grows as a square of types supported. Are you sure you need to support all types?
这篇关于如何在Kotlin中为每种Number类型实现发言权模数?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!