swift:将字符串转换为double的问题

时间:2016-09-29 12:25:38

标签: ios swift cocoa cocoa-touch

以下是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

所以,问题又开始了。

3 个答案:

答案 0 :(得分:12)

这里有两个不同的问题。首先 - 正如已经提到的那样 注释 - 二进制浮点数不能代表 数字8.7正好。 Swift使用IEEE 754标准进行表示 单精度和双精度浮点数,如果指定

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,则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 Optional 符合CustomStringConvertible,但是 CustomDebugStringConvertible。因此打印功能调用 debugDescription的{​​{1}}属性,依次为Optional 调用基础debugDescription的{​​{1}}。 因此 - 除了可选之外 - 数字输出是 与

相同
Double

但是let x = 8.7 print(x.debugDescription) // 8.6999999999999993 description之间的区别是什么? 对于浮点值?从Swift源代码可以看出 这最终都叫debugDescription Stubs.cpp中的函数,swift_floatingPointToString参数分别设置为Debugfalse。 这可以控制数字到字符串转换的精度:

true

有关这些常量的含义,请参阅http://en.cppreference.com/w/cpp/types/numeric_limits

  • int Precision = std::numeric_limits<T>::digits10; if (Debug) { Precision = std::numeric_limits<T>::max_digits10; } - 无需更改即可表示的小数位数
  • digits10 - 区分此类型所有值所需的小数位数。

因此max_digits10创建一个十进制数较少的字符串。那 string可以转换为description并返回给字符串 同样的结果。 Double创建一个包含更多十进制数字的字符串,以便这样做 任何两个不同的浮点值都会产生不同的输出。

摘要:

  • 大多数十进制数不能完全表示为二进制数 浮点值。
  • 浮动的debugDescriptiondescription方法 点类型使用不同的精度转换为a 串。因此,
  • 打印可选浮点值使用不同的转换精度,而不是打印非可选值。

因此,在您的情况下,您可能想要打开可选项 在打印之前:<​​/ p>

debugDescription

为了更好地控制,请使用let str = "8.7" if let d = Double(str) { print(d) // 8.7 } 或格式化 使用NSNumberFormatter格式打印。

另一种选择可以是使用%.<precision>f代替(NS)DecimalNumber (例如,对于货币金额),请参阅例如Round Issue in swift

答案 1 :(得分:1)

我会用:

df.columns = [['one', 'one'], ['one', 'two']]

答案 2 :(得分:0)

您可以使用此代码可能很有用。

print(str.doubleValue)