v-i*_*a-l 8 cocoa cocoa-touch ios swift
这是Xcode 7.3.1 playground中的一个简单代码:
var str = "8.7"
print(Double(str))
输出结果令人惊讶:
Optional(8.6999999999999993)
还,Float(str)给出:8.69999981
对这个家伙的任何想法或理由?任何对此的参考将不胜感激.
另外,我应该如何将"8.7"转换为8.7为Double(或Float)?
编辑
在swift中:
(str as NSString).doubleValue返回8.7
现在,那没关系.但我的问题仍然没有得到完整答案.我们找到了另一种选择,但为什么我们不能依赖Double("8.7").请更深入地了解这一点.
编辑2
("6.9"as NSString).doubleValue //打印6.9000000000000004
所以,问题又开始了.
Mar*_*n R 13
这里有两个不同的问题.首先 - 正如评论中已经提到的 - 二进制浮点数不能8.7精确地表示数字.Swift使用IEEE 754标准来表示单精度和双精度浮点数,如果指定的话
let x = 8.7
Run Code Online (Sandbox Code Playgroud)
然后存储最接近的可表示数字x,即
8.699999999999999289457264239899814128875732421875
Run Code Online (Sandbox Code Playgroud)
关于这一点的更多信息可以在优秀的Q&A Is浮点数学中找到?.
第二个问题是:为什么数字有时打印为"8.7",有时打印为"8.6999999999999993"?
let str = "8.7"
print(Double(str)) // Optional(8.6999999999999993)
let x = 8.7
print(x) // 8.7
Run Code Online (Sandbox Code Playgroud)
有什么Double("8.7")不同8.7?比另一个更准确吗?
要回答这些问题,我们需要知道print()
函数的工作原理:
CustomStringConvertible,则print函数调用其description属性并将结果输出到标准输出.CustomDebugStringConvertible,则print函数调用是debugDescriptionproperty并将结果打印到标准输出.的Double类型符合CustomStringConvertible,因此
let x = 8.7
print(x) // 8.7
Run Code Online (Sandbox Code Playgroud)
产生相同的输出
let x = 8.7
print(x.description) // 8.7
Run Code Online (Sandbox Code Playgroud)
但是会发生什么
let str = "8.7"
print(Double(str)) // Optional(8.6999999999999993)
Run Code Online (Sandbox Code Playgroud)
Double(str)是可选的,并struct Optional不会不
符合CustomStringConvertible,而是要
CustomDebugStringConvertible.因此,print函数调用debugDescription属性Optional,而属性又调用debugDescription底层属性Double.因此 - 除了可选之外 - 数字输出与in相同
let x = 8.7
print(x.debugDescription) // 8.6999999999999993
Run Code Online (Sandbox Code Playgroud)
但
浮点值description和debugDescription浮点值之间有什么区别?从夫特源代码的一个可以看到,无论最终调用swift_floatingPointToString
函数中Stubs.cpp,与Debug参数设置为false和true,分别.这可以控制数字到字符串转换的精度:
int Precision = std::numeric_limits<T>::digits10;
if (Debug) {
Precision = std::numeric_limits<T>::max_digits10;
}
Run Code Online (Sandbox Code Playgroud)
有关这些常量的含义,请参阅http://en.cppreference.com/w/cpp/types/numeric_limits:
digits10 - 可以无变化地表示的小数位数,max_digits10 - 区分此类型的所有值所需的小数位数.因此description创建一个十进制数较少的字符串.该字符串可以转换为a Double并返回到字符串,从而得到相同的结果.
debugDescription创建一个具有更多十进制数字的字符串,以便任何两个不同的浮点值将产生不同的输出.
摘要:
description和debugDescription方法使用不同的精度来转换为字符串.作为结果,因此,在您的情况下,您可能希望在打印之前打开可选项:
let str = "8.7"
if let d = Double(str) {
print(d) // 8.7
}
Run Code Online (Sandbox Code Playgroud)
为了更好地控制,使用NSNumberFormatter或格式化打印%.<precision>f格式.
另一种选择可以是(NS)DecimalNumber代替Double
(例如货币金额),参见例如swift中的Round Issue.
| 归档时间: |
|
| 查看次数: |
5121 次 |
| 最近记录: |