Here is a simple code in Xcode 7.3.1 playground:
以下是Xcode 7.3.1中的一个简单代码:
var str = "8.7" print(Double(str))
var str = "8.7"打印(双(str)
the output is suprising: Optional(8.6999999999999993)
输出是出乎意料的:可选(8.69999999999999999999999993)
also, Float(str)
gives: 8.69999981
同时,浮动(str)为:8.69999981
Any thoughts or reasons on this guys? Any references to this would be appreciated.
对这家伙有什么想法或理由吗?如能提及此事,将不胜感激。
Also, how should I then convert "8.7" to 8.7 as Double (or Float)?
另外,我应该如何将“8.7”转换为8.7作为Double(或Float)?
Edit
编辑
in swift:
迅速:
(str as NSString).doubleValue returns 8.7
作为NSString(str)。doubleValue返回8.7
Now, that is Ok. But my question, still, does not get a complete answer. We have found an alternative but why can we not rely on Double("8.7"). Please, give a deeper insight on this.
现在,这是好的。但是我的问题仍然没有得到一个完整的答案。我们已经找到了另一种选择,但为什么我们不能依赖双精度(“8.7”)呢?请给出一个更深刻的见解。
Edit 2
编辑2
("6.9" as NSString).doubleValue // prints 6.9000000000000004
(“6.9”NSString)。6.9000000000000004 doubleValue / /打印
So, the question opens up again.
这个问题又出现了。
3 个解决方案
#1
9
There are two different issues here. First – as already mentioned in the comments – a binary floating point number cannot represent the number 8.7
precisely. Swift uses the IEEE 754 standard for representing single- and double-precision floating point numbers, and if you assign
这里有两个不同的问题。首先,正如注释中已经提到的,二进制浮点数不能精确地表示8.7。Swift使用IEEE 754标准来表示单精度和双精度浮点数,如果您分配的话
let x = 8.7
then the closest representable number is stored in x
, and that is
然后,最接近的可表示数存储在x中,即。
8.699999999999999289457264239899814128875732421875
Much more information about this can be found in the excellent Q&A Is floating point math broken?.
更多关于这方面的信息可以在优秀的问答中找到:浮点数学被破坏了吗?
The second issue is: Why is the number sometimes printed as "8.7" and sometimes as "8.6999999999999993"?
第二个问题是:为什么数字有时印成“8.7”,有时印成“8.6999999999999999999993”?
let str = "8.7"
print(Double(str)) // Optional(8.6999999999999993)
let x = 8.7
print(x) // 8.7
Is Double("8.7")
different from 8.7
? Is one more precise than the other?
Double(“8.7”)与8.7不同吗?一个比另一个更精确吗?
To answer these questions, we need to know how the print()
function works:
要回答这些问题,我们需要知道print()函数是如何工作的:
- If an argument conforms to
CustomStringConvertible
, the print function calls itsdescription
property and prints the result to the standard output. - 如果参数符合CustomStringConvertible,打印函数调用其description属性并将结果打印到标准输出。
- Otherwise, if an argument conforms to
CustomDebugStringConvertible
, the print function calls isdebugDescription
property and prints the result to the standard output. - 否则,如果参数符合CustomDebugStringConvertible,打印函数调用是debugDescription属性,并将结果打印到标准输出。
- Otherwise, some other mechanism is used. (Not imported here for our purpose.)
- 否则,将使用其他一些机制。(不是为我们的目的进口的。)
The Double
type conforms to CustomStringConvertible
, therefore
因此,双类型符合CustomStringConvertible
let x = 8.7
print(x) // 8.7
produces the same output as
产生相同的输出
let x = 8.7
print(x.description) // 8.7
But what happens in
但是发生了什么
let str = "8.7"
print(Double(str)) // Optional(8.6999999999999993)
Double(str)
is an optional, and struct Optional
does not conform to CustomStringConvertible
, but to CustomDebugStringConvertible
. Therefore the print function calls the debugDescription
property of Optional
, which in turn calls the debugDescription
of the underlying Double
. Therefore – apart from being an optional – the number output is the same as in
Double(str)是可选的,而struct optional不符合CustomStringConvertible,而是CustomDebugStringConvertible。因此,print函数调用Optional的debugDescription属性,后者反过来调用底层Double的debugDescription。因此,除了是可选的之外,输出的数字与in相同
let x = 8.7
print(x.debugDescription) // 8.6999999999999993
But what is the difference between description
and debugDescription
for floating point values? From the Swift source code one can see that both ultimately call the swift_floatingPointToString
function in Stubs.cpp, with the Debug
parameter set to false
and true
, respectively. This controls the precision of the number to string conversion:
但是浮点值的description和debugDescription有什么区别呢?从Swift源代码可以看到,两者最终都在存根中调用swift_floatingPointToString函数。cpp,调试参数分别设置为false和true。它控制数字到字符串转换的精度:
int Precision = std::numeric_limits<T>::digits10;
if (Debug) {
Precision = std::numeric_limits<T>::max_digits10;
}
For the meaning of those constants, see http://en.cppreference.com/w/cpp/types/numeric_limits:
关于这些常量的含义,请参见http://en.cppreference.com/w/cpp/types/numeric_limits:
-
digits10
– number of decimal digits that can be represented without change, - digits10 -十进制数的数目,可以不加改变地表示,
-
max_digits10
– number of decimal digits necessary to differentiate all values of this type. - max_digits10 -区分此类型的所有值所需的十进制数。
So description
creates a string with less decimal digits. That string can be converted to a Double
and back to a string giving the same result. debugDescription
creates a string with more decimal digits, so that any two different floating point values will produce a different output.
因此,描述创建了一个小数位数较少的字符串。可以将该字符串转换为双字符串,然后返回一个字符串,得到相同的结果。debugDescription创建一个具有更多小数位数的字符串,因此任何两个不同的浮点值都将产生不同的输出。
Summary:
简介:
- Most decimal numbers cannot be represented exactly as a binary floating point value.
- 大多数十进制数不能精确地表示为二进制浮点值。
- The
description
anddebugDescription
methods of the floating point types use a different precision for the conversion to a string. As a consequence, - 浮点类型的描述和调试描述方法在转换到字符串时使用不同的精度。因此,
- printing an optional floating point value uses a different precision for the conversion than printing a non-optional value.
- 打印可选浮点值与打印不可选值相比,转换使用不同的精度。
Therefore in your case, you probably want to unwrap the optional before printing it:
因此,在您的情况下,您可能需要在打印之前打开可选的包装:
let str = "8.7"
if let d = Double(str) {
print(d) // 8.7
}
For better control, use NSNumberFormatter
or formatted printing with the %.<precision>f
format.
为了更好地控制,使用NSNumberFormatter或格式化打印%。 <精度> f格式。
Another option can be to use (NS)DecimalNumber
instead of Double
(e.g. for currency amounts), see e.g. Round Issue in swift.
另一种选择是使用(NS)小数而不是双位数(例如货币数量),参见swift中的Round问题。
#2
1
I would use:
我将使用:
let doubleValue = NSNumberFormatter().numberFromString(str)?.doubleValue
#3
0
You can use this code may be useful.
您可以使用这段代码可能会有用。
print(str.doubleValue)
#1
9
There are two different issues here. First – as already mentioned in the comments – a binary floating point number cannot represent the number 8.7
precisely. Swift uses the IEEE 754 standard for representing single- and double-precision floating point numbers, and if you assign
这里有两个不同的问题。首先,正如注释中已经提到的,二进制浮点数不能精确地表示8.7。Swift使用IEEE 754标准来表示单精度和双精度浮点数,如果您分配的话
let x = 8.7
then the closest representable number is stored in x
, and that is
然后,最接近的可表示数存储在x中,即。
8.699999999999999289457264239899814128875732421875
Much more information about this can be found in the excellent Q&A Is floating point math broken?.
更多关于这方面的信息可以在优秀的问答中找到:浮点数学被破坏了吗?
The second issue is: Why is the number sometimes printed as "8.7" and sometimes as "8.6999999999999993"?
第二个问题是:为什么数字有时印成“8.7”,有时印成“8.6999999999999999999993”?
let str = "8.7"
print(Double(str)) // Optional(8.6999999999999993)
let x = 8.7
print(x) // 8.7
Is Double("8.7")
different from 8.7
? Is one more precise than the other?
Double(“8.7”)与8.7不同吗?一个比另一个更精确吗?
To answer these questions, we need to know how the print()
function works:
要回答这些问题,我们需要知道print()函数是如何工作的:
- If an argument conforms to
CustomStringConvertible
, the print function calls itsdescription
property and prints the result to the standard output. - 如果参数符合CustomStringConvertible,打印函数调用其description属性并将结果打印到标准输出。
- Otherwise, if an argument conforms to
CustomDebugStringConvertible
, the print function calls isdebugDescription
property and prints the result to the standard output. - 否则,如果参数符合CustomDebugStringConvertible,打印函数调用是debugDescription属性,并将结果打印到标准输出。
- Otherwise, some other mechanism is used. (Not imported here for our purpose.)
- 否则,将使用其他一些机制。(不是为我们的目的进口的。)
The Double
type conforms to CustomStringConvertible
, therefore
因此,双类型符合CustomStringConvertible
let x = 8.7
print(x) // 8.7
produces the same output as
产生相同的输出
let x = 8.7
print(x.description) // 8.7
But what happens in
但是发生了什么
let str = "8.7"
print(Double(str)) // Optional(8.6999999999999993)
Double(str)
is an optional, and struct Optional
does not conform to CustomStringConvertible
, but to CustomDebugStringConvertible
. Therefore the print function calls the debugDescription
property of Optional
, which in turn calls the debugDescription
of the underlying Double
. Therefore – apart from being an optional – the number output is the same as in
Double(str)是可选的,而struct optional不符合CustomStringConvertible,而是CustomDebugStringConvertible。因此,print函数调用Optional的debugDescription属性,后者反过来调用底层Double的debugDescription。因此,除了是可选的之外,输出的数字与in相同
let x = 8.7
print(x.debugDescription) // 8.6999999999999993
But what is the difference between description
and debugDescription
for floating point values? From the Swift source code one can see that both ultimately call the swift_floatingPointToString
function in Stubs.cpp, with the Debug
parameter set to false
and true
, respectively. This controls the precision of the number to string conversion:
但是浮点值的description和debugDescription有什么区别呢?从Swift源代码可以看到,两者最终都在存根中调用swift_floatingPointToString函数。cpp,调试参数分别设置为false和true。它控制数字到字符串转换的精度:
int Precision = std::numeric_limits<T>::digits10;
if (Debug) {
Precision = std::numeric_limits<T>::max_digits10;
}
For the meaning of those constants, see http://en.cppreference.com/w/cpp/types/numeric_limits:
关于这些常量的含义,请参见http://en.cppreference.com/w/cpp/types/numeric_limits:
-
digits10
– number of decimal digits that can be represented without change, - digits10 -十进制数的数目,可以不加改变地表示,
-
max_digits10
– number of decimal digits necessary to differentiate all values of this type. - max_digits10 -区分此类型的所有值所需的十进制数。
So description
creates a string with less decimal digits. That string can be converted to a Double
and back to a string giving the same result. debugDescription
creates a string with more decimal digits, so that any two different floating point values will produce a different output.
因此,描述创建了一个小数位数较少的字符串。可以将该字符串转换为双字符串,然后返回一个字符串,得到相同的结果。debugDescription创建一个具有更多小数位数的字符串,因此任何两个不同的浮点值都将产生不同的输出。
Summary:
简介:
- Most decimal numbers cannot be represented exactly as a binary floating point value.
- 大多数十进制数不能精确地表示为二进制浮点值。
- The
description
anddebugDescription
methods of the floating point types use a different precision for the conversion to a string. As a consequence, - 浮点类型的描述和调试描述方法在转换到字符串时使用不同的精度。因此,
- printing an optional floating point value uses a different precision for the conversion than printing a non-optional value.
- 打印可选浮点值与打印不可选值相比,转换使用不同的精度。
Therefore in your case, you probably want to unwrap the optional before printing it:
因此,在您的情况下,您可能需要在打印之前打开可选的包装:
let str = "8.7"
if let d = Double(str) {
print(d) // 8.7
}
For better control, use NSNumberFormatter
or formatted printing with the %.<precision>f
format.
为了更好地控制,使用NSNumberFormatter或格式化打印%。 <精度> f格式。
Another option can be to use (NS)DecimalNumber
instead of Double
(e.g. for currency amounts), see e.g. Round Issue in swift.
另一种选择是使用(NS)小数而不是双位数(例如货币数量),参见swift中的Round问题。
#2
1
I would use:
我将使用:
let doubleValue = NSNumberFormatter().numberFromString(str)?.doubleValue
#3
0
You can use this code may be useful.
您可以使用这段代码可能会有用。
print(str.doubleValue)