如何在Kotlin中为每种Number类型实现发言权模数? [英] How to implement floor modulo for every Number type in Kotlin?

查看:167
本文介绍了如何在Kotlin中为每种Number类型实现发言权模数?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我目前正在学习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

...或类似于Java的

...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屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆