Swift中浮点数的定点表示形式

问题描述 投票:1回答:2

我正在尝试在Swift中准确表示浮点数。假设我们有一个数字let doubleNumber = 16.756。问题在于实际数字类似于16.7560009。此外,由于处理器不平等,在不同的电话上,例如16.7559991。定点算法应该是解决此类问题的方法,但是我不知道如何在Swift中解决它。说实话,也不用其他语言。那么如何在Swift中创建浮点数的定点表示形式?

我问的原因是,在跨设备准确地模拟物理时,浮点数值的微小差异会导致完全不同的物理模拟。

swift fixed-point
2个回答
3
投票

您提供的数字表示您正在使用Float,而不是Double。 Float仅具有约6位数字的精度,Double则具有约15位精度。请记住,CGFloat是Float或Double,所以请不要使用它。

Swift使用IEEE 754标准浮点算法。只要您始终使用Double,不同的处理器之间就不会有任何区别。

现在到了非常关键的一点:如果不同处理器上的浮点算法之间的细微差异产生了完全不同的模拟,那么这两种模拟都与现实无关,因此完全没有用。或它们都显示出许多可能结果中的一种,然后再次显示出哪种显示都没有区别。


-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
© www.soinside.com 2019 - 2024. All rights reserved.