在我的iOS應用中,我有一個用CGPoints構建的形狀類。我使用encodeCGPoint:forKey將它保存到一個文件中。我讀回來了。這一切都有效。用NSCoder對CGPoint進行編碼,具有全精度
但是,我讀入的CGPoint值與我保存的值不完全相同。 CGFloat值的低位不穩定。所以CGPointEqualToPoint返回NO,這意味着我的isEqual方法返回NO。這給我帶來麻煩和痛苦。
顯然,從一開始就精確地序列化浮點數是一件麻煩事。但在這種情況下,最好的方法是什麼?我能想到的幾個:
- 使用encodeFloat代替encodeCGPoint(?會是無助於)
- 乘以256.0我x和y的值保存之前寫出來的x和y值(它們是都會在-1和1之間,所以這可能有幫助嗎?)
- 使用encodeDouble而不是encodeCGPoint寫出x和y值(仍可能錯誤地舍入最低位?)
- 轉換爲NSUInteger和寫出來使用encodeInt32(icky,但它會工作,對不對?)
- 接受損失的精度,並實現我的isEqual方法使用內厄普西隆比較,而不是CGPointEqualToPoint(嘆氣)
編輯-ADD:所以這個問題,我離開了爲簡單的下半年,是我必須爲這些形狀對象實現散列方法。
散射花車是也一個可怕的痛苦(見「Good way to hash a float vector?」),它原來或多或少無效我的問題。該工具包的encodeCGPoint方法以令人討厭的方式舍入其float值 - 這實際上是將它們打印爲具有%g格式的字符串 - 所以我無法使用它並仍然使哈希可靠。因此,我不得不寫我自己的encodePoint函數。只要我這樣做,我還不如寫一個能準確編碼數值的數字。 (將兩個32位浮點數複製到一個64位整數字段中,不,它不是便攜式的,但是這只是iOS而且我正在做這個折衷。)
可靠地存儲CGPoints,我可以回到精確的比較和我想要的任何舊的散列函數。公差範圍對我沒有任何幫助,所以我只是沒有將它們用於此應用程序。
如果我想散列和耐受性比較,我會爲N 顯著數字,沒有一個固定的距離小量的公差範圍內比較值。 (也就是說,我希望0.123456比較接近0.123457,但我也希望1234.56比較接近1234.57)。對於大數值和小數值,這對於浮點數學錯誤都是穩定的。我沒有示例代碼,但是從frexpf()函數開始,它不應該太難。
卡爾,一個CGFloat的不是雙精度(在iOS)。但是,我必須同意CGPointEqualToPoint對座標進行按位比較並不是很有用。滾動您自己的isEqual並保持CGPointEqualToPoint清晰,這似乎只在您直接複製座標時纔有用。 –
謝謝史蒂文;我沒有真正查看實際類型。同樣的推理立場。即使是單精度浮點數也有7位數的小數精度,它具有*得到*足以滿足OP的目的。 –
是的,7位數字應該讓你的UIView *令人難以置信*接近你想要顯示的屏幕像素;-) –