我试图准确地表示Swift中的浮点数。假设我们有一个数字/etc/nginx/mime.types
。这个问题是实际的数字是let doubleNumber = 16.756
。更重要的是,在不同的手机上它是16.7560009
,例如,由于处理器不平等。定点算术应该是这类问题的答案,但我不知道如何在Swift中解决它。说实话,也不是其他语言。那么如何在Swift中创建浮点数的定点表示?
我之所以要问的是,在跨设备精确模拟物理时,浮点数值的微小差异会导致完全不同的物理模拟。
答案 0 :(得分:3)
您提供的数字表示您使用的是Float,而不是Double。 Float只有大约6位数的精度,Double大约有15位。并且记住CGFloat是Float或Double,所以不要使用它。
Swift使用IEEE 754标准浮点运算。只要您始终使用Double,不同处理器之间应该没有任何区别。
现在有一个非常关键的问题:如果不同处理器上的浮点运算之间的细微差别会产生完全不同的模拟,那么这两种模拟都与现实无关,因此完全没用。或者他们都显示了许多可能的结果之一,然后再次显示你所展示的那个没有区别。
答案 1 :(得分:-1)
import Foundation
let f1: Float = 0x1p-149
f1.isZero // false
let f0: Float = 0x1p-150
f0.isZero // true
Float(f1 / 2) == Float(f1 / 3) // true ??? what ??? f1 is zero?
let d1 = 0x1p-1074
d1.isZero // false
let d0 = 0x1p-1075
d0.isZero // true
d1 / 2 == d1 / 3 // true
print("value of Float next to 0 is \(f1) or as Double \(Double(f1))")
print("value of Double next to 0 is \(d1)")
/*
value of Float next to 0 is 1.4013e-45 or as Double 1.40129846432482e-45
value of Double next to 0 is 4.94065645841247e-324
*/
我建议所有需要进行浮点计算的人 What Every Computer Scientist Should Know About Floating-Point Arithmetic
一个例子,正确的算法如何减少错误
import Foundation
var arr: [Float] = []
for i in 0...100 {
arr.append(Float(random()))
}
let sum1 = arr.reduce(0.0) { $0 + $1 }
var sum2 = arr[0]
var c:Float = 0.0
for j in 1..<arr.count {
let y: Float = arr[j] - c
let t: Float = sum2 + y
c = t - sum2 - y
sum2 = t
}
print(sum1, sum2, "and the 'small' difference is:", sum2 - sum1)
// 1.18466e+11 1.18466e+11 and the 'small' difference is: 8192.0
// what do you thing, which one is more precise ?
// sum1 or sum2 ????
// lets try the same with naive Double approach
let sum3 = arr.map{ Double($0) }.reduce(0.0) { $0 + $1 }
print(Double(sum1)-sum3) // -11268.0
print(Double(sum2)-sum3) // -3076.0