私のiOSアプリケーションでは、CGPointsで構築されたシェイプクラスがあります。私はencodeCGPoint:forKeyを使用してファイルに保存します。私はそれをすべて読んで読んだ。NSCoderでCGPointを完全精度で符号化する
しかし、私が読み込んだCGPoint値は、私が保存した値と正確には同じではありません。 CGFloat値の下位ビットは安定していません。したがって、CGPointEqualToPointはNOを返します。つまり、isEqualメソッドはNOを返します。これは私にトラブルと痛みを引き起こします。
明らかに、浮動小数点数を正確にシリアライズすることは、時間の始めから面倒です。しかし、この状況では、最善のアプローチは何ですか?私はいくつか考えることができます:
- encodeFloatを使用して、xとyの値を書き出す代わりにencodeCGPoint(全くその役立つだろう?)
- (彼らはしているそれらを保存する前に256.0で、私のxとyの値を乗算します
- encodeCGPointの代わりにencodeDoubleを使用してxとyの値を書き出します(最下位ビットを間違って丸めてもかまいません)。
- NSUIntegerにキャストします。 encodeInt32を使ってそれらを書き出してください(うまくいくでしょうが)。
- 精度の、そして内-イプシロンの比較ではなく、CGPointEqualToPoint(ため息)
EDIT-ADDを使用するために私のisEqualメソッドを実装します。だから私は簡単にするために除外された問題、の後半は、ありますこれらのシェイプオブジェクトのハッシュメソッドを実装する必要があります。
ハッシング浮動小数点はでも恐ろしい痛み(「Good way to hash a float vector?」参照)、それは多かれ少なかれ私の質問を無効にします。ツールキットのencodeCGPointメソッドは、浮動小数点値を迷惑な方法で丸めます。文字通り%g形式の文字列にそれらを出力します。したがって、私はそれを使用してもハッシュを信頼できる方法ではありません。
したがって、独自のencodePoint関数を作成する必要があります。私がそれをしている限り、値を正確に符号化するものを書くかもしれません。 (2つの32ビット浮動小数点を64ビット整数フィールドにコピーしてください。いいえ、ポータブルではありませんが、これはiOS専用であり、そのトレードオフです)
CGPointsを正確に正確に格納すると、正確な比較と私が望む古いハッシュ関数に戻ります。許容範囲は私のために何もしないので、私はこのアプリケーションに使用していません。
私はと寛容の比較をハッシュたい場合、私はN 有効数字、ない一定の距離イプシロンの許容範囲内の値を比較することと思います。 (すなわち、私は0.123456を0.123457の近くで比較したいと思いますが、1234.56を1234.57の近くで比較したいと思っています。)これは、大きな値と小さい値の両方で浮動小数点数学エラーに対して安定します。私はそれのためのサンプルコードを持っていないが、frexpf()関数から始まり、あまりにも難しくはありません。
をカール、CGFloat()はiOSで倍精度ではありません。しかし、私は、CGPointEqualToPointが座標のビット単位の比較を行うことはあまり有用ではないことに同意する必要があります。独自のisEqualをロールして、CGPointEqualToPointから明確にしてください。これは、座標を直接コピーしている場合にのみ有効です。ありがとうSteven; –
私は実際に実際のタイプを調べなかった。同じ種類の推論が立っている。単精度浮動小数点数でも7桁の小数精度がありますが、OPの目的には十分に*得られています。 –
ええと、7桁の数字は、あなたが表示したい画面のピクセルの近くにUIView *を信じられないほど近づけます;-) –