Kotlin:检查双精度值是否仅在0.0到1.0之间,步进0.1

Kotlin:检查双精度值是否仅在0.0到1.0之间,步进0.1,kotlin,Kotlin,检查双精度值是否仅在 {.0,1,…9,1.0} 价值观 现在我正在做 setOf(.0, .1, .2, .3, .4, .5, .6, .7, .8, .9, 1.0) 并检查双精度值是否包含 有更简单/优雅的解决方案吗?您可以使用 编辑 如注释中所述,由于复杂的双重计算,中的简单不起作用。因此,您可以添加自己的检查功能: val acceptableAccuracy = 1e-15 infix fun Double.nearlyIn(sequence: Sequence<Doubl

检查双精度值是否仅在
{.0,1,…9,1.0}
价值观

现在我正在做

setOf(.0, .1, .2, .3, .4, .5, .6, .7, .8, .9, 1.0)
并检查双精度值是否包含

有更简单/优雅的解决方案吗?

您可以使用

编辑

如注释中所述,由于复杂的
双重计算,
中的简单
不起作用。因此,您可以添加自己的检查功能:

val acceptableAccuracy = 1e-15
infix fun Double.nearlyIn(sequence: Sequence<Double>) = 
    sequence.any { this in (it - acceptableAccuracy..it + acceptableAccuracy) }
你可以和我一起去

编辑

如注释中所述,由于复杂的
双重计算,
中的简单
不起作用。因此,您可以添加自己的检查功能:

val acceptableAccuracy = 1e-15
infix fun Double.nearlyIn(sequence: Sequence<Double>) = 
    sequence.any { this in (it - acceptableAccuracy..it + acceptableAccuracy) }

因为你只担心十位数的位置,所以我只移动它一次,然后检查0..10:

fun Double.isSpecial() = (this * 10.0) in (0..10).map(Int::toDouble)
使用play.kotlinlang.org进行测试:

fun main() {
  listOf(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0).forEach(::checkSpecial)
  listOf(0.01, 0.11, 0.22, 1.01).forEach(::checkSpecial)
}

fun checkSpecial(value: Double) {
  println("$value isSpecial = ${value.isSpecial()}")
}
产出:

0.0 isSpecial = true
0.1 isSpecial = true
0.2 isSpecial = true
0.3 isSpecial = true
0.4 isSpecial = true
0.5 isSpecial = true
0.6 isSpecial = true
0.7 isSpecial = true
0.8 isSpecial = true
0.9 isSpecial = true
1.0 isSpecial = true
0.01 isSpecial = false
0.11 isSpecial = false
0.22 isSpecial = false
1.01 isSpecial = false
如果您不太担心优雅,而更关心性能,您可以:

fun Double.isSpecial() = when (this) {
    0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 -> true
    else -> false
}

这样可以避免完全分配任何集合或范围。如果范围不是动态的,我个人会这样做。

因为你只担心十位数的位置,我只需要移动它一次,然后检查0..10:

fun Double.isSpecial() = (this * 10.0) in (0..10).map(Int::toDouble)
使用play.kotlinlang.org进行测试:

fun main() {
  listOf(0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0).forEach(::checkSpecial)
  listOf(0.01, 0.11, 0.22, 1.01).forEach(::checkSpecial)
}

fun checkSpecial(value: Double) {
  println("$value isSpecial = ${value.isSpecial()}")
}
产出:

0.0 isSpecial = true
0.1 isSpecial = true
0.2 isSpecial = true
0.3 isSpecial = true
0.4 isSpecial = true
0.5 isSpecial = true
0.6 isSpecial = true
0.7 isSpecial = true
0.8 isSpecial = true
0.9 isSpecial = true
1.0 isSpecial = true
0.01 isSpecial = false
0.11 isSpecial = false
0.22 isSpecial = false
1.01 isSpecial = false
如果您不太担心优雅,而更关心性能,您可以:

fun Double.isSpecial() = when (this) {
    0.0, 0.1, 0.2, 0.3, 0.4, 0.5, 0.6, 0.7, 0.8, 0.9, 1.0 -> true
    else -> false
}

这样可以避免完全分配任何集合或范围。如果这个范围不是动态的,我个人会这样做。

如果您想检查0.1的任何双精度步骤,就可以这样做。 乘以10,检查结果是否为整数

fun isSpecial(v:Double) : Boolean {
    val y = v*10
    return y == y.toInt().toDouble()
}

除非您明确只想要0.0-1.0?

如果您想要检查0.1的任何双精度步骤,则可以执行此操作。 乘以10,检查结果是否为整数

fun isSpecial(v:Double) : Boolean {
    val y = v*10
    return y == y.toInt().toDouble()
}

除非你明确地只想要0.0-1.0?

乘以10,看看这个值是否是整数?你如何检查结果的小数是否都是0?@Dachstein老实说,除非数字变化很大,您现在拥有的集合似乎简单易懂。乘以10,看看该值是否为整数?如何检查结果的小数是否都是0?@Dachstein老实说,除非数字变化很大,否则您现在拥有的集合似乎简单易懂。不幸的是,0.1+0.1+0.1不是0.3:(不幸的是,0.1+0.1+0.1不是0.3:(有趣的解决方案。谢谢,尽管这是一个“正确的”解决方案根据OP声明的要求,它让我感到不舒服,因为它比较了两个相等的值。这不是比较一个值,比如说,正好是0.3;实际上是比较一个值正好等于编译器遇到文本值“0.3”时创建的IEEE二进制表示在源代码中。它们是两个不同的东西。我更愿意与给定的容差进行比较。这是一个公平的观点。我猜这取决于值是如何生成的,但与给定的容差进行比较肯定会更安全。有趣的解决方案。谢谢,尽管这是一个“正确的”解决方案根据OP声明的要求,它让我感到不舒服,因为它比较了两个相等的值。这不是比较一个值,比如说,正好是0.3;实际上是比较一个值正好等于编译器遇到文本值“0.3”时创建的IEEE二进制表示在源代码中。它们是两个不同的东西。我更愿意与给定的容差进行比较。这是一个公平的观点。我猜这取决于值是如何生成的,但与给定的容差进行比较肯定会更安全。