由于计算机只能表示二进制整数和小数,因为并不是所有浮点数都能准确表示为二进制数,这些浮点数在计算机中的表示是不精确的。
我们判断两个浮点数A和B是否相等,并不能直接用==,而需要用abs(A - B) < FLT_EPSILON来判断,FLT_EPSILON是最小单精度浮点数。
问题描述:
近日做语音播报距离的时候遇到一个问题。需要先将以米作单位的距离d,分解为xx公里xx百x十米(个位数字直接舍掉),然后进行播报。例如:2017.123米,应该播报为2公里10米。但是实际播报的是2公里9米。
问题分析:
在使用函数操作的时候没有问题,但是使用扩展操作时,误差被放大了,导致精度偏差。
func test() {
let d: Double = 2017.123
self.testDouble(floor(d / 10) / 100)
_ = (floor(d / 10) / 100).ext_distanceDecompose()
}
func testDouble(_ d: Double) {
let str = String(format: "%.3f", (d * 1000) / 1000)
let distArr = str.components(separatedBy: ".")
print("\(d) \(distArr)")
}
func ext_distanceDecompose() -> [String] {
var distArray: [String] = []
let distStr = String(format: "%.3f", floor(self * 1000) / 1000)
let distArr = distStr.components(separatedBy: ".")
var front: Int = Int(distArr[0])!
var after: Int = Int(distArr.last!)!
...
print("\(self) \(distArray)")
return distArray
}
输出的结果是:
2.01 ["2", "010"]
2.01 ["2", "9"]
修改后:
func test() {
let d: Double = 2017.123
self.testDouble(floor(d / 10) / 100)
_ = 2017.ext_distanceDecompose1()
}
func testDouble(_ d: Double) {
let str = String(format: "%.3f", (d * 1000) / 1000)
let distArr = str.components(separatedBy: ".")
print("\(d) \(distArr)")
}
func ext_distanceDecompose1() -> [String] {
var distArray: [String] = []
let distStr = String(format: "%.3f", floor(self / 10) / 100)
let distArr = distStr.components(separatedBy: ".")
var front: Int = Int(distArr[0])!
var after: Int = Int(distArr.last!)!
print("\(self) \(distArray)")
return distArray
}
输出结果:
2.01 ["2", "010"]
2017.0 ["2", "10"]
参考:
http://blog.csdn.net/renwotao2009/article/details/51637163