Kotlin float / int间接比较

时间:2019-05-30 20:06:40

标签: generics kotlin casting floating-point

对于一个项目,我正在尝试实现一个Bit类,该类可以完成所有通常的工作。

如果给定值为Number,则构造函数应该能够使用任何Bit并将0的内部状态设置为0,否则将其设置为{ {1}}。

所有方法都适用于整数输入,但是当我浮动时……显然1不等于0.0

0

现在是问题:

class Bit(value: Number) {
    var value: Int = (value != 0).toInt() // I implemented Bool-to-Int myself
}

我认为这是某种近似误差,但是当我尝试println(Bit(0).value) // Prints 0 println(Bit(0f).value) // Prints 1 时,我得到了print(0f != 0)。但是,比较通过构造函数的数字没有问题。

我觉得这里有一些我不知道的隐藏的类型转换魔术,所以我的问题基本上是“为什么这不符合预期的行为,以及使它按预期的行为运行的一种优雅方法?”

2 个答案:

答案 0 :(得分:1)

我无法准确地告诉您为什么它的行为不如您预期,但是我可以给您一个简单的解决方法!

Number接口虽然没有您想要的强大,但是它提供的主要功能是将其值转换为任何标准数值类型的一种方法。您可以这样使用:

class Bit(value: Number) {
    var value = if (value.toDouble() == 0.0) 0 else 1
}

这将适用于所有Number实现:ByteDoubleFloatIntLongShortAtomicIntegerAtomicLongBigDecimalStriped64,以及您编写或导入的任何其他文件。

(无论您做什么,我建议您也覆盖value的设置器,以确保它只保留0或1。)

答案 1 :(得分:1)

这与docs中所述的值表示形式被装箱有关。

您已经注意到,您无法比较不同的类型(当FloatInt用本机表示时)。但是您并没有这样做,而是使用了Number类型。

考虑以下示例:

println(0.0f == 0)  // error: Operator '==' cannot be applied to 'Float' and 'Int'
val n : Number = 0L  // this forces value to be boxed
println(n == 0)   // compiles and prints false

首先,编译器警告您无法执行比较。但是,如果将数值与对象一起装箱,则可以使用equalsTo运算符。

只有当双方的类型和值都相同时,您会发现它返回true

不想在游行队伍中大吃一惊,但是实现类的正确方法是为每种数字类型声明单独的构造函数。这样可以防止编译器将值装箱,并让您正确地确定相等性:

class Bit constructor(value : Boolean) {
    val value = if(value) 1 else 0

    constructor(value : Int) : this(value == 0)
    constructor(value : Float) : this(value == 0f)
    constructor(value : Long) : this(value == 0L)
    // etc
}