Swift - 浮点值作为字典中的键?
Swift - Floating-point values as keys in a Dictionary?
是的,我已经做了研究,我能找到的最接近我的问题的页面是:
this page 一点帮助也没有。
也就是说,在Swift[中使用浮点值作为键是否安全(可靠)? =43=]字典?具体来说,CGFloat,Apple 文档说它实际上是 64 位系统上的 Double。
P.S。 (这很重要)- 我的 CGFloat 值将总是 以 .0 或 .5 作为小数部分结尾。示例 - 13、13.5、14、14.5 等。这会对此类字典查找的可靠性产生影响吗?
var dictionary: [CGFloat: MyObject] = [:]
...
// Could this type of lookup fail ?
if let mappedObject = dictionary[13.5] {
...
}
我有一个独特的用例,需要将某些对象映射到这些 CGFloat 值以便稍后快速查找。
根据我在单元测试中的经验,我知道 XCTAssertEqual 在比较两个浮点类型时有时会失败,而不使用“accuracy”参数。所以,我担心使用 CGFloats 作为键会导致后续查找失败,因为传入的键可能会偏离 0.0000000001 或类似的东西,因为浮点类型的底层表示。
谢谢。
编辑 -(感谢@Sweeper)是的,我确实考虑过使用 Int 键,通过使用以下转换将 CGFloat 转换为 Int:
intKey = Int(lroundf(Float(cgFloatKey * 2.0))
但是,我担心这个 ^ 转换(必须在每次查找时完成)需要足够的开销以使其不值得。
我在这里可能完全错了,也许这些操作快如闪电。任何人都可以评论每次执行查找时这种操作的效率吗?
您的担忧是有道理的,您知道 XCTAssertEqual
可能由于浮点值的工作方式而无法给出预期的结果,因此使用浮点值作为键与键查找所依赖的问题相同关于平等。
考虑另一种方式,比如使用合适的整数值作为键。
XCTAssertEqual
在比较浮点数据时不会失败。当且仅当参数不相等时,它才会生成失败,这是正确的行为。
如果参数不相等但如果用精确的数学计算本来会相等,这是因为在某些先前的操作中存在舍入误差,而不是在 XCTAssertEqual
中。对浮点数的担忧在于,对它们的算术运算和数学函数是对实际算术的近似,因此计算结果可能与精确数学所期望的理想结果不同。因此,不能使用 XCTAssertEqual
来确保使用近似值计算的两个结果相等,而实际上由于近似值它们可能不相等。其原因完全在于算术近似值,而不在于 XCTAssertEqual
.
的行为
如果您的值的小数部分始终为 0 或 ½,则这些问题不适用(除非您的数字可能有很大偏差,例如生成 13½ 而不是 13)。因此,如果您的数字始终是您想要的精确值,则对算术近似值的担忧不适用,它们将适合用作字典键。
是的,我已经做了研究,我能找到的最接近我的问题的页面是: this page 一点帮助也没有。
也就是说,在Swift[中使用浮点值作为键是否安全(可靠)? =43=]字典?具体来说,CGFloat,Apple 文档说它实际上是 64 位系统上的 Double。
P.S。 (这很重要)- 我的 CGFloat 值将总是 以 .0 或 .5 作为小数部分结尾。示例 - 13、13.5、14、14.5 等。这会对此类字典查找的可靠性产生影响吗?
var dictionary: [CGFloat: MyObject] = [:]
...
// Could this type of lookup fail ?
if let mappedObject = dictionary[13.5] {
...
}
我有一个独特的用例,需要将某些对象映射到这些 CGFloat 值以便稍后快速查找。
根据我在单元测试中的经验,我知道 XCTAssertEqual 在比较两个浮点类型时有时会失败,而不使用“accuracy”参数。所以,我担心使用 CGFloats 作为键会导致后续查找失败,因为传入的键可能会偏离 0.0000000001 或类似的东西,因为浮点类型的底层表示。
谢谢。
编辑 -(感谢@Sweeper)是的,我确实考虑过使用 Int 键,通过使用以下转换将 CGFloat 转换为 Int:
intKey = Int(lroundf(Float(cgFloatKey * 2.0))
但是,我担心这个 ^ 转换(必须在每次查找时完成)需要足够的开销以使其不值得。
我在这里可能完全错了,也许这些操作快如闪电。任何人都可以评论每次执行查找时这种操作的效率吗?
您的担忧是有道理的,您知道 XCTAssertEqual
可能由于浮点值的工作方式而无法给出预期的结果,因此使用浮点值作为键与键查找所依赖的问题相同关于平等。
考虑另一种方式,比如使用合适的整数值作为键。
XCTAssertEqual
在比较浮点数据时不会失败。当且仅当参数不相等时,它才会生成失败,这是正确的行为。
如果参数不相等但如果用精确的数学计算本来会相等,这是因为在某些先前的操作中存在舍入误差,而不是在 XCTAssertEqual
中。对浮点数的担忧在于,对它们的算术运算和数学函数是对实际算术的近似,因此计算结果可能与精确数学所期望的理想结果不同。因此,不能使用 XCTAssertEqual
来确保使用近似值计算的两个结果相等,而实际上由于近似值它们可能不相等。其原因完全在于算术近似值,而不在于 XCTAssertEqual
.
如果您的值的小数部分始终为 0 或 ½,则这些问题不适用(除非您的数字可能有很大偏差,例如生成 13½ 而不是 13)。因此,如果您的数字始终是您想要的精确值,则对算术近似值的担忧不适用,它们将适合用作字典键。