let dic : [Double : Double] = [1.1 : 2.3, 2.3 : 1.1, 1.2 : 2.3]
print(dic)// [2.2999999999999998: 1.1000000000000001, 1.2: 2.2999999999999998, 1.1000000000000001: 2.2999999999999998]
let double : Double = 2.3
let anotherdouble : Double = 1.1
print(double) // 2.3
print(anotherdouble) // 1.1
我不明白为什么编译器以不同方式打印字典中的值? 我在Swift 3,Xcode 8上。这是一个错误或一些奇怪的方法来优化东西吗?
更奇怪的是:
有些价值观会过去,有些价值会低于预期值,有些则会保持原样! 1.1小于1.1000000000000001而2.3小于2.2999999999999998,1.2仅为1.2
答案 0 :(得分:14)
正如评论中已经提到的,Double
无法存储
值1.1
完全正确。 Swift使用(像许多其他语言一样)
根据{{3}}的二进制浮点数
标准。
可以表示为1.1
的最接近Double
的号码是
1.100000000000000088817841970012523233890533447265625
,可以表示为2.3
的最接近Double
的号码是
2.29999999999999982236431605997495353221893310546875
打印该数字表示将其转换为字符串 再次使用十进制表示,这是用不同的方式完成的 精度,取决于您打印数字的方式。
从IEEE 754的源代码可以看到description
方法
Dictionary
对密钥和值使用debugPrint()
,
并debugPrint(x)
打印x.debugDescription
的值
(如果x
符合CustomDebugStringConvertible
)。
另一方面,如果print(x)
符合,x.description
会调用x
到CustomStringConvertible
。
所以你看到的是description
的不同输出
和debugDescription
的{{1}}:
Double
从Swift源代码可以看出
两者都使用print(1.1.description) // 1.1
print(1.1.debugDescription) // 1.1000000000000001
HashedCollections.swift.gyb中的函数,swift_floatingPointToString()
参数分别设置为Debug
和false
。
此参数控制数字到字符串转换的精度:
true
有关这些常量的含义,请参阅Stubs.cpp:
int Precision = std::numeric_limits<T>::digits10;
if (Debug) {
Precision = std::numeric_limits<T>::max_digits10;
}
- 无需更改即可表示的小数位数digits10
- 区分此类型所有值所需的小数位数。因此max_digits10
创建一个十进制数较少的字符串。那
string可以转换为description
并返回给字符串
同样的结果。
Double
创建一个包含更多十进制数字的字符串,以便这样做
任何两个不同的浮点值都会产生不同的输出。
答案 1 :(得分:0)
是的,Swift在将其存储到字典
中时使用二进制浮点数使用字典作为[Double:Any],如果您的数字是32位则使用Float然后向上转换为AnyObject
见下面的例子
let strDecimalNumber = "8.37"
var myDictionary : [String: Any] = [:]
myDictionary["key1"] = Float(strDecimalNumber) as AnyObject // 8.369999999999999
myDictionary["key2"] = Double(strDecimalNumber) as AnyObject //8.369999999999999
myDictionary["key3"] = Double(8.37) as AnyObject //8.369999999999999
myDictionary["key4"] = Float(8.37) as AnyObject //8.37
myDictionary["key5"] = 8.37 // 8.3699999999999992
myDictionary["key6"] = strDecimalNumber // "8.37" it is String
myDictionary["key7"] = strDecimalNumber.description // "8.37" it is String
myDictionary["key8"] = Float(10000000.01) // 10000000.0
myDictionary["key9"] = Float(100000000.01) // 100000000.0
myDictionary["key10"] = Float(1000000000.01) // 1e+09
myDictionary["key11"] = Double(1000000000.01) // 1000000000.01
print(myDictionary)
myDictionary将打印为
[“key1”:8.37,“key2”:8.369999999999999,“key3”:8.369999999999999, “key4”:8.37,“key5”:8.3699999999999992,“key6”:“8.37”,“key7”:“8.37”,“key8”: 10000000.0,“key9”:100000000.0,“key10”:1e + 09,“key11”:1000000000.01]
正如Martin R在上面的回答中所提到的,使用.description将被视为String而不是实际的Float