比较两个相同的Double值返回false Swift 3

Kes*_*Xie 7 ios swift

我试图比较两个相同的纬度,它是类型的Double,当我打印结果时,它被评估为false.

print("spot latitude: " + String(spot.location.latitude))
print("first object: " + String(firstSpot.location.latitude))  
print(spot.location.latitude == firstSpot.location.latitude)
Run Code Online (Sandbox Code Playgroud)

输出:

spot latitude: 32.8842183049047
first object: 32.8842183049047
false
Run Code Online (Sandbox Code Playgroud)

任何人都知道发生了什么?

And*_*rea 11

比较双打中的平等很少给你预期的答案,这是由于如何存储双打.您可以创建自定义运算符,请记住您应该使用一些准确性.
要了解更多信息,您可以查看此答案,即使它说的是ObjC,原则也是超级有效的.
由于我在线检查有同样的问题,我在apple dev论坛上找到了这个答案.
这个功能应该可以做到,你可以轻松创建一个自定义运算符:

 func doubleEqual(_ a: Double, _ b: Double) -> Bool {
    return fabs(a - b) < Double.ulpOfOne
}
Run Code Online (Sandbox Code Playgroud)

我试图从swift 2.x转换为3.x似乎宏DBL_EPSILON不再可用了.


Ger*_*iet 7

使用==比较double或float值将不会在大多数编程语言中给出预期结果,这意味着您认为应该相等的数字实际上略有不同.相反,如果差值低于某个阈值,则计算绝对差值并将数字处理为相等.有关更多说明,请参阅使用epsilon将double比较为零.


dim*_*iax 7

斯威夫特 5、4

四舍五入的解决方案可能是获得接近值的最佳选择:

extension Double {
  static func equal(_ lhs: Double, _ rhs: Double, precise value: Int? = nil) -> Bool {
    guard let value = value else {
      return lhs == rhs
    }
        
    return lhs.precised(value) == rhs.precised(value)
  }

  func precised(_ value: Int = 1) -> Double {
    let offset = pow(10, Double(value))
    return (self * offset).rounded() / offset
  }
}

// values retrieving
a: 64.3465535142464, b: 64.3465535142464
    
// values debug description
a: 64.346553514246409, b: 64.346553514246395

// calculations
a == b // false
a.precised(10) == b.precised(10) // true
// or
Double.equal(a, b) // false
Double.equal(a, b, precise: 10) // true
Run Code Online (Sandbox Code Playgroud)

如果使用带有 epsilon 的修正,无论如何我都会得到假等于双打:

// values retrieving
a: 64.3465535142464, b: 64.3465535142464

// values debug description
a: 64.346553514246409, b: 64.346553514246395

// calculations
a == b // false
a - b  // 1.4210854715202e-14
a - b < .ulpOfOne // false
Run Code Online (Sandbox Code Playgroud)


Kir*_*row 7

您可以使用此扩展

extension FloatingPoint {
    func isNearlyEqual(to value: Self) -> Bool {
        return abs(self - value) <= .ulpOfOne
    }
}
Run Code Online (Sandbox Code Playgroud)

或根据本指南

extension FloatingPoint {
    func isNearlyEqual(to value: Self) -> Bool {
        let absA = abs(self)
        let absB = abs(value);
        let diff = abs(self - value);

        if self == value { // shortcut, handles infinities
            return true
        } else if self == .zero || value == .zero || (absA + absB) < Self.leastNormalMagnitude {
            // a or b is zero or both are extremely close to it
            // relative error is less meaningful here
            return diff < Self.ulpOfOne * Self.leastNormalMagnitude
        } else { // use relative error
            return diff / min((absA + absB), Self.greatestFiniteMagnitude) < .ulpOfOne;
        }
    }
}
Run Code Online (Sandbox Code Playgroud)