我从用户那里收到一个浮点数,并根据定义的增量(0.1,0.5,0.01等)检查它是否有效。例如,如果增量为0.5,则1.0,1.5,2.0有效但1.2不有效。我正在使用modulo检查它是否有效。
if (input % increment) == 0 {
println("Pass")
} else {
println("Fail")
}
问题是当增量为0.1时,输入的大多数有效值都被检测为无效。
我使用了this answer中给出的公式,它改进了有效输入的检测,但大部分时间仍然失败。
答案 0 :(得分:4)
你的问题是0.1在二进制中不能完全表示,而例如0.5。这意味着0.1 * 5不等于0.5。这很像十进制,其中(1/3)*3≃0.3333333* 3 = 0.99999999不是1.要解决这类问题,你可以引入一个epsilon。 epsilon是一个非常小的值,你可以检查你的结果是否与你想要的值只有很小的距离,如果你希望这个值是正确的。
答案 1 :(得分:3)
要处理小数点后面有一个数字的数字:
if (input * 10) % (increment * 10) == 0 {
println("Pass")
} else {
println("Fail")
}
要在小数点后处理多个数字的数字,只需增加倍数即可。例如,if (input * 100000) % (increment * 100000) == 0
。
答案 2 :(得分:3)
基于James Snook's answer,我最终得到了这个解决方案。
let epsilon = 1e-6
let division = input / increment
let diff = abs(division - round(division))
if (diff < epsilon) {
println("Pass")
} else {
println("Fail")
}
答案 3 :(得分:2)
我相信模数只适用于整数,如果我是对的,你应该自己做一个解决方法,看看给定的数字是否为多数,转换为:除法的结果必须是整数。 代码应该是这样的:
let floatDivision = input/increment;
let isInteger = floor(floatDivision) == floatDivision // true
if (isInteger) {
println("Pass")
} else {
println("Fail")
}
这应该适用于任何增量编号(甚至超过一个小数点)。
修改强>
作为詹姆斯赛义德,1.2超过0.1的浮点除法并不完全编码为12而是11.9999 ...所以我在比较中添加了epsilon:
let input = 1.2;
let increment = 0.1;
let epsilon = 0.00000000000001;
let floatDivision = input/increment;
let dif = abs(round(floatDivision) - floatDivision);
println(String(format: "%.20f", floatDivision)); // 11.99999999999999822364
println(String(format: "%.20f", round(floatDivision))); // 12.00000000000000000000
println(String(format: "%.20f", dif)) // 0.00000000000000177636
let isInteger = dif < epsilon // Pass if (isInteger) {
println("Pass") } else {
println("Fail") }
祝你好运。