[解決済み】浮動小数点値の比較はどのくらい危険か?
質問
知っている
UIKit
用途
CGFloat
というのは、解像度に依存しない座標系だからです。
しかし、毎回、例えば
frame.origin.x
は
0
気持ち悪くなる。
if (theView.frame.origin.x == 0) {
// do important operation
}
はありません。
CGFloat
と比較した場合、誤検出の可能性があります。
==
,
<=
,
>=
,
<
,
>
?
浮動小数点で、精度不足の問題があるそうです。
0.0000000000041
例えば
は
Objective-C
は比較時にこれを内部的に処理するか、あるいは
origin.x
とは比較されません。
0
を真とするか?
解決方法は?
まず第一に、浮動小数点値はその動作において"random"ではないことです。厳密な比較は、現実の世界の多くの用途で意味を持ちます。しかし、浮動小数点を使用するのであれば、それがどのように動作するのかを知っておく必要があります。浮動小数点が実数のように動くと思い込んでいると、すぐにコードが壊れてしまいます。浮動小数点の結果が大きなランダムファズを持っていると仮定すると(ここの回答のほとんどが示唆するように)、最初は動作しているように見えても、最終的には大きなエラーや壊れたコーナーケースを持つことになるコードを取得することになります。
まず、浮動小数点を使ったプログラミングをしたい人は、これを読んでおくといいでしょう。
コンピュータ科学者が浮動小数点演算について知っておくべきこと
はい、全部読んでください。それが負担なら、読む時間ができるまで、計算には整数・固定小数点を使うべきでしょう :-)
さて、そうは言っても、正確な浮動小数点数の比較の最大の問題点は、次のようなことに尽きると思います。
-
ソースに記述した値、あるいは
scanf
またはstrtod
, 存在しない を浮動小数点値として使用すると、無言で最も近い近似値に変換されます。demon9733さんの回答はこのことを指しています。 -
実際の結果を表すのに十分な精度がないため、多くの結果が丸め込まれてしまうことです。これを見ることができる簡単な例として
x = 0x1fffffe
とy = 1
をフロートとして使用します。ここでx
は仮数で24ビットの精度を持ち(ok),かつy
は1ビットだけですが、足し算をするとそのビットは重なる場所になく、結果には25ビットの精度が必要になります。その代わり、丸められ (0x2000000
で、デフォルトの丸めモードで)。 -
正しい値を得るためには無限に多くの場所が必要なため、多くの結果が丸められてるという事実です。これには、1/3 のような有理数(10 進法では無限大の桁数を必要とします)と 1/10 (2 進法では 5 は 2 のべき乗ではないのでこれも無限大の桁数を必要とします)の両方と、完全平方でないものの平方根のような非理数の結果が含まれます。
-
二重丸め。一部のシステム(特に x86)では、浮動小数点式はその公称型よりも高精度で評価されます。つまり、上記のような丸めが行われる場合、2回の丸めが行われることになります。最初に高い精度の型に丸められ、次に最終的な型に丸められます。例えば、10進数で1.49を整数に丸めた場合(1)と、まず小数点以下1桁に丸め(1.5)、その結果を整数に丸めた場合(2)とを考えてみましょう。コンパイラ(特にGCCのようなバギーで不適合なコンパイラ)の動作が予測できないからです。
-
超越関数 (
trig
,exp
,log
など)は,結果が正しく丸められるように指定されているわけではありません。結果は,精度の最後の場所で1単位以内で正しくなるように指定されているだけです(通常,このような場合は 1ulp ).
浮動小数点コードを書くときは、結果が不正確になる可能性のある数値の扱いに留意し、それに応じて比較を行う必要があります。多くの場合、quot;epsilon"で比較することは理にかなっていますが、そのepsilonは、quot;epsilon"の値に基づいている必要があります。 比較する数値の大きさ 絶対定数ではありません。(絶対定数のイプシロンが有効な場合、浮動小数点ではなく固定小数点がその仕事に適したツールであることを強く示唆します!)
編集する。 特に、マグニチュード相対イプシロン検査は、以下のようになります。
if (fabs(x-y) < K * FLT_EPSILON * fabs(x+y))
ここで
FLT_EPSILON
の定数です。
float.h
(で置き換える)。
DBL_EPSILON
に対して
double
または
LDBL_EPSILON
に対して
long double
s)と
K
は、計算の累積誤差が確実に以下の範囲に収まるような定数です。
K
の単位で計算します(誤差の境界の計算が正しいかどうかわからない場合は
K
を、計算結果の数倍大きくしてください)。
最後に、これを使用する場合、ゼロ付近では特別な注意が必要であることに注意してください。
FLT_EPSILON
はデノーマルに対して意味をなさない。手っ取り早いのは、それを作ることでしょう。
if (fabs(x-y) < K * FLT_EPSILON * fabs(x+y) || fabs(x-y) < FLT_MIN)
で、同様に
DBL_MIN
をダブルスで使用する場合。
関連
-
[解決済み] arc4randomとarc4random_uniformの違いは何ですか?重複
-
[解決済み] 1ビットのセット、クリア、トグルはどのように行うのですか?
-
[解決済み] 文字列をfloatやintにパースするにはどうしたらいいですか?
-
[解決済み] 文字列が数値(float)であるかどうかを確認するにはどうすればよいですか?
-
[解決済み] キーボードがあるときに、UITextFieldを編集開始時に上に移動させるには?
-
[解決済み] カスタムオブジェクトを含むNSMutableArrayをソートするにはどうすればよいですか?
-
[解決済み] Objective-Cで、ある文字列が他の文字列を含んでいるかどうかを調べるにはどうすればよいですか?
-
[解決済み] iOSのバージョンを確認する方法を教えてください。
-
[解決済み] 除算を強制的に浮動小数点にするにはどうしたらいいですか?除算は0に切り捨てられ続けますか?
-
[解決済み] JavaScriptで浮動小数点数の精度を扱うには?
最新
-
nginxです。[emerg] 0.0.0.0:80 への bind() に失敗しました (98: アドレスは既に使用中です)
-
htmlページでギリシャ文字を使うには
-
ピュアhtml+cssでの要素読み込み効果
-
純粋なhtml + cssで五輪を実現するサンプルコード
-
ナビゲーションバー・ドロップダウンメニューのHTML+CSSサンプルコード
-
タイピング効果を実現するピュアhtml+css
-
htmlの選択ボックスのプレースホルダー作成に関する質問
-
html css3 伸縮しない 画像表示効果
-
トップナビゲーションバーメニュー作成用HTML+CSS
-
html+css 実装 サイバーパンク風ボタン
おすすめ
-
[解決済み] arc4randomとarc4random_uniformの違いは何ですか?重複
-
[解決済み] iOS 8で位置情報サービスが利用できない
-
[解決済み] NSStringにパーセント記号を追加する方法
-
[解決済み] Xcode 4でNSZombieEnabledを設定するにはどうすればよいですか?
-
[解決済み] ブロック内の変数をブロック外の変数に代入する
-
[解決済み】浮動小数点値の比較はどのくらい危険か?
-
[解決済み】Objective-Cのコードをユニットテストするのに最適な方法は何ですか?
-
[解決済み】メインスレッドでタスクを実行するGCD
-
[解決済み】iOS 7.0とシステム劣化で無効なコンテキスト0x0が表示される
-
[解決済み】ストーリーボードで、複数のコントローラで使用するためのカスタムセルを作成する方法は?