检查double值是否仅存在于
的集合中的简单/优雅的解决方案是什么?
{.0, .1, .. .9, 1.0}
值。
现在我在做
setOf(.0, .1, .2, .3, .4, .5, .6, .7, .8, .9, 1.0)
,然后检查Double值是否包含。
是否有更简单/优雅的解决方案?
答案 0 :(得分:1)
您可以使用sequences来实现。
fun contains(d: Double) = d in generateSequence(0.0) { it + 0.1 }.takeWhile { it <= 1.0 }
如果要使其更短,请添加step
函数,例如Int
序列有一个函数。
infix fun ClosedRange<Double>.step(step: Double): Sequence<Double> =
generateSequence(start) { it + step }.takeWhile { it <= endInclusive }
fun contains(d: Double) = d in 0.0..1.0 step 0.1
修改
如评论中所述,由于复杂的in
计算,简单的Double
不起作用。因此,您可以添加自己的检查功能:
val acceptableAccuracy = 1e-15
infix fun Double.nearlyIn(sequence: Sequence<Double>) =
sequence.any { this in (it - acceptableAccuracy..it + acceptableAccuracy) }
然后,您需要在上面的代码中进行一些更改:
fun contains(d: Double) = d nearlyIn (0.0..1.0 step 0.1)
答案 1 :(得分:1)
由于您只真正担心十位,所以我只需要移动一次并检查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
}
避免完全分配任何集合或范围。如果范围不是动态的,我个人会考虑使用。
答案 2 :(得分:0)
如果您要检查0.1的步长是否为两倍,将执行此操作。 乘以10,检查结果是否为整数。
fun isSpecial(v:Double) : Boolean {
val y = v*10
return y == y.toInt().toDouble()
}
除非您明确只需要0.0-1.0?