var str =“8.7”
打印(双人间(STR))
输出令人惊讶:
可选(8.6999999999999993)
另外,Float(str)给出:8.69999981
对这个家伙的任何想法或原因?
任何对此的引用都将不胜感激.
另外,我应该如何将“8.7”转换为8.7为Double(或Float)?
编辑
在迅速:
(str为NSString).doubleValue返回8.7
现在,那没关系.但我的问题仍然没有得到完整答案.我们找到了另一种选择,但为什么我们不能依赖Double(“8.7”).请更深入地了解这一点.
编辑2
(“6.9”as NSString).doubleValue //打印6.9000000000000004
所以,这个问题又开始了.
解决方法
注释 – 二进制浮点数不能代表
准确地说是8.7. Swift使用IEEE 754标准进行表示
单精度和双精度浮点数,如果指定的话
let x = 8.7
然后,最接近的可表示数字存储在x中,即
8.699999999999999289457264239899814128875732421875
关于这方面的更多信息可以在优秀中找到
Q& A 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
双倍(“8.7”)与8.7不同吗?比一个更准确
另一个?
要回答这些问题,我们需要知道print()
功能有效:
>如果参数符合CustomStringConvertible,则print函数调用其description属性并打印结果
到标准输出.
>否则,如果参数符合CustomDebugStringConvertible,
print函数调用是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可选不
符合CustomStringConvertible,但要符合
CustomDebugStringConvertible.因此打印功能调用
Optional的debugDescription属性,反过来
调用底层Double的debugDescription.
因此 – 除了可选之外 – 数字输出是
与中相同
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会创建一个十进制数较少的字符串.那
string可以转换为Double并返回给字符串
同样的结果.
debugDescription创建一个包含更多十进制数字的字符串,以便这样做
任何两个不同的浮点值都会产生不同的输出.
摘要:
>大多数十进制数不能完全表示为二进制数
浮点值.
>浮动的描述和debugDescription方法
点类型使用不同的精度转换为a
串.作为结果,
>打印可选浮点值使用与转换非可选值不同的转换精度.
因此,在您的情况下,您可能想要打开可选项
在打印之前:
let str = "8.7" if let d = Double(str) { print(d) // 8.7 }
为了更好地控制,请使用NSNumberFormatter或格式化
使用%.< precision> f格式打印.
另一个选项可以是使用(NS)DecimalNumber而不是Double
(例如,对于货币金额),请参阅例如Round Issue in swift.