下面是Xcode 7.3.1操场中的简单代码:
var str = "8.7" print(Double(str))
输出是令人惊讶的:Optional(8.6999999999999993)
此外,Float(str)
给出:8.69999981
对这家伙有什么想法或理由吗?如能提及这一点,将不胜感激。
另外,我应该如何将" 8.7“转换为双(或浮动)的8.7?
编辑
迅速:
(str as NSString).doubleValue返回8.7
现在,这没什么。但我的问题,仍然没有一个完整的答案。我们已经找到了另一种选择,但为什么我们不能依靠双倍(“8.7”)。请对此给予更深入的了解。
编辑2
("6.9“为NSString).doubleValue //打印6.9000000000000004
所以,这个问题又开始了。
发布于 2016-09-29 10:17:44
这里有两个不同的问题。首先,正如注释中已经提到的,二进制浮点数不能精确地表示数字8.7
。Swift使用IEEE 754标准来表示单精度和双精度浮点数,如果您指定
let x = 8.7
然后最近可表示的数字存储在x
中,即
8.699999999999999289457264239899814128875732421875
有关这一点的更多信息可以在优秀的Q&A 浮点数数学坏了吗?中找到。
第二个问题是:为什么这个数字有时印成"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
,则print函数调用其description
属性并将结果打印到标准输出。CustomDebugStringConvertible
,则打印函数调用是debugDescription
属性,并将结果打印到标准输出。因此,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
。因此,print函数调用Optional
的Optional
属性,后者反过来调用底层Double
的debugDescription
。因此--除了是可选的--数字输出与
let x = 8.7
print(x.debugDescription) // 8.6999999999999993
但是对于浮点值而言,description
和debugDescription
有什么区别呢?从Swift源代码可以看出,两者最终都在Stubs.cpp中调用Stubs.cpp函数,Debug
参数分别设置为false
和true
。这控制数字到字符串转换的精度:
int Precision = std::numeric_limits<T>::digits10;
if (Debug) {
Precision = std::numeric_limits<T>::max_digits10;
}
有关这些常量的含义,请参见限制
digits10
-可以不改变地表示的十进制数,max_digits10
-区分这种类型的所有值所需的十进制数。因此,description
创建了一个小数位数较少的字符串。可以将该字符串转换为Double
,然后返回给出相同结果的字符串。debugDescription
创建一个具有更多十进制数字的字符串,因此任何两个不同的浮点值都会产生不同的输出。
摘要:
description
和debugDescription
方法对字符串的转换使用不同的精度。因此,因此,在您的示例中,您可能希望在打印可选选项之前展开它:
let str = "8.7"
if let d = Double(str) {
print(d) // 8.7
}
为了更好地控制,使用NSNumberFormatter
或格式化打印与%.<precision>f
格式。
另一种选择是使用(NS)DecimalNumber
而不是Double
(例如货币金额),参见迅速发行。
发布于 2016-09-29 04:30:41
我会用:
let doubleValue = NSNumberFormatter().numberFromString(str)?.doubleValue
https://stackoverflow.com/questions/39770303
复制相似问题