Swift:双转换不一致。如何正确比较双打?

时间:2015-03-09 16:40:30

标签: swift double

我有一个非常简单的功能,可将温度从˚C转换为˚K。

func convertKelvinToCelsius(temp:Double) ->Double {
        return temp - 273.15
}

我有一个单元测试来驱动这个功能。这就是问题所在:

  func testKelvinToCelsius(){
            var check1 = conv.convertKelvinToCelsius(200.00) // -73.149999999999977
            var check2 = 200.00 - 273.15                     // -73.149999999999977
            var check3 = Double(-73.15)                      // -73.150000000000006

            //Passes
            XCTAssert(conv.convertKelvinToCelsius(200.00).description == Double(-73.15).description, "Shoud convert from celsius kelvin")

            //Fails
            XCTAssert(conv.convertKelvinToCelsius(200.00) == Double(-73.15), "Shoud convert from celsius kelvin")
     }

当您添加断点并检查check1,check2和check3的值时,它们非常有趣:

check1  Double  -73.149999999999977
check2  Double  -73.149999999999977
check3  Double  -73.150000000000006

问题:

  1. 为什么Swift会为check1 / check2和check3返回不同的值

  2. 我怎样才能通过第二次测试,因为像我一样写测试1气味。为什么我必须将双打转换为字符串才能比较它们?

  3. 最后,当我println check1,check2和check3时,它们都打印为'-73.15'。为什么?为什么不准确打印,不要混淆程序员!?

  4. 重现:

    只需在你的游乐场中输入200 - 273.15 == -73.15并观看它false !!

3 个答案:

答案 0 :(得分:5)

这是浮点值的预期行为。 They cannot be 100% accurately represented.

您可以使用XCTAssertEqualWithAccuracy函数断言浮点值在给定的范围内。

println打印相同值的原因是因为它在内部将它们舍入为两位小数(我假设)。

答案 1 :(得分:2)

这不是特定于Swift的问题,这与如何在计算机中创建十进制数以及它们的精度有关。您需要使用DBL_EPSILON。

答案 2 :(得分:1)

与大多数语言一样,Swift使用二进制浮点数。

使用二进制浮点数,可以准确表示某些数字,但大多数数字都不能表示。可以准确表示的是整数,除非它们非常大(例如,100000000000000.0很好),并且这样的整数乘以或除以2的幂(7.375很好,它是59.0 / 8,但7.3不是&t; t) 。

每个浮点运算都会给出精确的结果,四舍五入到最接近的浮点数。所以你得到了

200.0 -> Exactly 200
273.15 -> A number very close to 273.15
200 - 273.15 -> A number very close to -73.15
-73.15 -> A number very close to -73.15

如果比较两个非常接近-73.15的数字,它们不一定相等。这不是==运算符的问题;一个人将正确地确定他们是否平等。问题是两个数字实际上可能不同。