这是 Xcode 7.3.1 Playground 中的简单代码:
var str = "8.7"
打印(双(str))
输出令人惊讶:
可选(8.69999999999999993)
此外,Float(str)
给出:8.69999981
对这些人有什么想法或理由吗? 任何对此的引用将不胜感激。
另外,我应该如何将“8.7”转换为 8.7 作为 Double(或 Float)?
编辑
快速:
(str as NSString).doubleValue 返回 8.7
现在,没关系。但我的问题仍然没有得到完整的答案。我们已经找到了替代方案,但为什么我们不能依赖 Double("8.7")。请对此有更深入的了解。
编辑2
("6.9"as NSString).doubleValue//打印 6.9000000000000004
所以,问题再次出现。
最佳答案
这里有两个不同的问题。首先——正如已经提到的
注释 – 二进制 float 不能表示
号码8.7
恰恰。 Swift 使用 IEEE 754 标准来表示
单精度和 double float ,并且如果您分配
let x = 8.7
那么最接近的可表示数字存储在 x
中,那就是
8.699999999999999289457264239899814128875732421875
有关这方面的更多信息可以在优秀的 问答Is floating point math broken? .
<小时/>第二个问题是:为什么数字有时会打印为“8.7” 有时为“8.6999999999999993”?
let str = "8.7"
print(Double(str)) // Optional(8.6999999999999993)
let x = 8.7
print(x) // 8.7
是Double("8.7")
不同于8.7
?有一个比
另一个?
要回答这些问题,我们需要知道 print()
如何
功能工作原理:
- 如果参数符合
CustomStringConvertible
,打印函数调用其description
属性并打印结果 到标准输出。 - 否则,如果参数符合
CustomDebugStringConvertible
, 打印函数调用是debugDescription
属性(property)和打印品 结果到标准输出。 - 否则,将使用其他一些机制。 (这里没有为我们导入 目的。)
Double
类型符合CustomStringConvertible
,因此
let x = 8.7
print(x) // 8.7
产生与
相同的输出let x = 8.7
print(x.description) // 8.7
但是发生了什么
let str = "8.7"
print(Double(str)) // Optional(8.6999999999999993)
Double(str)
是可选,并且 struct Optional
没有
符合CustomStringConvertible
,但要
CustomDebugStringConvertible
。因此打印函数调用
debugDescription
Optional
的属性(property),这反过来又
调用debugDescription
底层证券Double
。
因此,除了可选之外,数字输出为
与
let x = 8.7
print(x.debugDescription) // 8.6999999999999993
但是 description
之间有什么区别?和debugDescription
对于浮点值?从Swift源码可以看出
最终两者都调用 swift_floatingPointToString
函数位于 Stubs.cpp ,与 Debug
参数设置为false
和true
, 分别。
这控制数字到字符串转换的精度:
int Precision = std::numeric_limits<T>::digits10;
if (Debug) {
Precision = std::numeric_limits<T>::max_digits10;
}
有关这些常量的含义,请参阅 http://en.cppreference.com/w/cpp/types/numeric_limits :
-
digits10
– 可以不改变地表示的十进制位数, -
max_digits10
– 区分该类型的所有值所需的小数位数。
所以description
创建一个小数位数较少的字符串。那
字符串可以转换为 Double
并返回给定的字符串
相同的结果。
debugDescription
创建一个具有更多十进制数字的字符串,以便
任何两个不同的浮点值都会产生不同的输出。
摘要:
- 大多数十进制数无法精确表示为二进制数 浮点值。
description
和debugDescription
漂浮的方法 点类型使用不同的精度来转换为 字符串。结果,- 打印可选浮点值与打印非可选值使用不同的转换精度。
因此,在您的情况下,您可能想要打开可选的 打印之前:</p>
let str = "8.7"
if let d = Double(str) {
print(d) // 8.7
}
为了更好地控制,请使用NSNumberFormatter
或格式化
使用%.<precision>f
打印格式。
另一个选择是使用 (NS)DecimalNumber
而不是Double
(例如货币金额),请参见Round Issue in swift .
关于ios - swift:将字符串转换为 double 时出现问题,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41038585/