我们发现,如果一个是另一个的负数,则无法通过它们的 hashValue 区分两个小数。我们使用 Decimals 作为结构中的字段,并且该结构实现了 Hashable 以便能够放入集合中。然后,我们的业务逻辑要求所有字段都是唯一的,因此所有字段并组合为 hashValue。这意味着我们的十进制字段是另一个的负数并且其余字段实际上相等的两个结构,那么整个结构被认为是相等的。这不是我们想要的。
游乐场代码:
for i in 0..<10 {
let randomNumber: Int = Int.random(in: 0..<10000000)
let lhs = Decimal(integerLiteral: randomNumber)
let rhs = Decimal(integerLiteral: -randomNumber)
print("Are \(lhs) and \(rhs)'s hashValues equal? \(lhs.hashValue == rhs.hashValue)")
print("Are \(randomNumber) and \(-randomNumber)'s hashValues equal? \(randomNumber.hashValue == (-randomNumber).hashValue)\n")
}
doubleLiteral
使用而不是进行测试时也会发生同样的情况integerLiteral
。
解决方法是直接比较小数,如果其他部分需要,可以选择将其包含在 hashValue 中。
这种行为是有意的吗?尾数是相同的,所以我猜他们不被认为是相等的原因是因为符号不包含在十进制的 hashValue 中?