gpt4 book ai didi

ios - 使用 NSCoder 对 CGPoint 进行全精度编码

转载 作者:塔克拉玛干 更新时间:2023-11-02 20:26:09 33 4
gpt4 key购买 nike

在我的 iOS 应用程序中,我有一个使用 CGPoints 构建的形状类。我使用 encodeCGPoint:forKey 将它保存到一个文件中。我读回去了。一切正常。

但是,我读入的CGPoint值与我保存的值并不完全相等。 CGFloat 值的低位不稳定。所以 CGPointEqualToPoint 返回 NO,这意味着我的 isEqual 方法返回 NO。这给我带来了麻烦和痛苦。

显然,精确地序列化 float 从一开始就是一件麻烦事。但在这种情况下,最好的方法是什么?我能想到几个:

  • 使用 encodeFloat 而不是 encodeCGPoint 写出 x 和 y 值(这会有帮助吗?)
  • 在保存它们之前将我的 x 和 y 值乘以 256.0(它们大致都在 -1 和 1 之间,所以这可能有帮助?)
  • 使用 encodeDouble 而不是 encodeCGPoint 写出 x 和 y 值(仍然可能不正确地舍入最低位?)
  • 转换为 NSUInteger 并使用 encodeInt32 将它们写出来(有点恶心,但它会起作用,对吧?)
  • 接受精度损失,并实现我的 isEqual 方法以使用内 epsilon 比较而不是 CGPointEqualToPoint(叹息)

EDIT-ADD:因此,为了简单起见,我忽略了问题的后半部分,即我必须为这些形状对象实现散列方法。

散列 float 也是一个可怕的痛苦(参见“Good way to hash a float vector?”),事实证明它或多或少使我的问题无效。该工具包的 encodeCGPoint 方法以一种恼人的方式对其浮点值进行舍入——它实际上是将它们打印成具有 %g 格式的字符串——所以我无法使用它并仍然使散列可靠。

因此,我不得不编写自己的 encodePoint 函数。只要我这样做,我还不如编写一个对值进行精确编码的代码。 (将两个 32 位 float 复制到一个 64 位整数字段中,不,它不可移植,但这仅适用于 iOS,我正在做出权衡。)

有了 CGPoints 的可靠精确存储,我可以返回到精确比较和我想要的任何旧哈希函数。公差范围对我没有任何作用,所以我只是没有将它们用于此应用程序。

如果我想要散列公差比较,我会比较 N 有效数字公差内的值,而不是固定距离 epsilon。 (也就是说,我希望 0.123456 比较接近 0.123457,但我也希望 1234.56 比较接近 1234.57。)对于大值和小值,这对于 float 学错误都是稳定的。我没有相关的示例代码,但从 frexpf() 函数开始,应该不会太难。

最佳答案

直接比较 float 通常不是正确的游戏计划。试试 many other options 之一.您问题的最佳解决方案可能是您最后的建议;不过,我不知道为什么会有“叹息”。 double float 具有大约 16 位十进制数字的精度 - 很有可能您的程序实际上不需要那么多的精度。

关于ios - 使用 NSCoder 对 CGPoint 进行全精度编码,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/6699260/

33 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com