floatを使用して作成できる最大の「相対」レベルは何ですか?


13

ダンジョンシージやKSPのようなゲームでデモンストレーションされたように、浮動小数点がどのように機能するかによって、十分に大きなレベルで不具合が発生し始めます。精度を落とさずに1e-20を1e20に追加することはできません。

レベルのサイズを制限することを選択した場合、オブジェクトが途切れるまで移動できる最小速度を計算するにはどうすればよいですか?

回答:


26

32ビットの浮動小数点には23ビットの仮数があります。

手段は、各番号は1.xxx XXX、XXX、XXX、XXX、XXX、XXX、XX回いくつかのパワー未満で極端に小さい非正規化数を除いて各Xは二進数である2、0または1(のように表される2126 -それらは1ではなく0で始まりますが、以下では無視します)

したがって、および2 i + 1 )の範囲では、± 2 i 24 )の精度内で任意の数を表すことができます22+1±224

例として、i = 0の場合、この範囲の最小数は(2 ^ 0)* 1 = 1です。次に小さい数は(2 ^ 0)*(1 + 2 ^ -23)です。1 + 2 ^ -24を表す場合は、どちらの場合も2 ^ -24の誤差のため、切り上げまたは切り捨てる必要があります。

In this range:                You get accuracy within:
-----------------------------------------------
         0.25   -     0.5    2^-26 = 1.490 116 119 384 77 E-08
         0.5    -     1      2^-25 = 2.980 232 238 769 53 E-08
         1     -      2      2^-24 = 5.960 464 477 539 06 E-08
         2     -      4      2^-23 = 1.192 092 895 507 81 E-07
         4     -      8      2^-22 = 2.384 185 791 015 62 E-07
         8     -     16      2^-21 = 4.768 371 582 031 25 E-07
        16     -     32      2^-20 = 9.536 743 164 062 5  E-07
        32     -     64      2^-19 = 1.907 348 632 812 5  E-06
        64     -    128      2^-18 = 0.000 003 814 697 265 625
       128    -     256      2^-17 = 0.000 007 629 394 531 25
       256    -     512      2^-16 = 0.000 015 258 789 062 5
       512    -   1 024      2^-15 = 0.000 030 517 578 125
     1 024    -   2 048      2^-14 = 0.000 061 035 156 25
     2 048    -   4 096      2^-13 = 0.000 122 070 312 5
     4 096    -   8 192      2^-12 = 0.000 244 140 625
     8 192   -   16 384      2^-11 = 0.000 488 281 25
    16 384   -   32 768      2^-10 = 0.000 976 562 5
    32 768   -   65 536      2^-9  = 0.001 953 125
    65 536   -  131 072      2^-8  = 0.003 906 25
   131 072   -  262 144      2^-7  = 0.007 812 5
   262 144   -  524 288      2^-6  = 0.015 625
   524 288 -  1 048 576      2^-5  = 0.031 25
 1 048 576 -  2 097 152      2^-4  = 0.062 5
 2 097 152 -  4 194 304      2^-3  = 0.125
 4 194 304 -  8 388 608      2^-2  = 0.25
 8 388 608 - 16 777 216      2^-1  = 0.5
16 777 216 - 33 554 432      2^0   = 1

したがって、ユニットがメートルの場合、16 484-32 768バンド(原点から約16-33 km)あたりのミリメートルの精度が失われます。

別のベースユニットを使用することでこれを回避できると一般に考えられていますが、それは重要ではない相対的な精度であるため、実際にはそうではありません。

  • 単位としてセンチメートルを使用すると、1 048 576-2 097 152バンド(原点から10-21 km)でミリメートル精度が失われます

  • ヘクタールを単位として使用すると、128-256バンド(原点から13-26 km)でミリメートル精度が失われます

...したがって、単位を4桁以上変更すると、数十キロメートルの範囲でミリメートル精度が失われます。私たちがシフトしているのは、そのバンドの正確にヒットする場所(ベース10とベース2の番号付けの不一致による)であり、プレイ可能な領域を大幅に拡張していません。

ゲームが許容できる不正確さの程度は、ゲームプレイ、物理シミュレーション、エンティティサイズ/描画距離、レンダリング解像度などの詳細に依存するため、正確なカットオフを設定するのは困難です。レンダリングは原点から50 kmでうまく見えるかもしれませんが、弾丸が壁を介してテレポートしている、または繊細なゲームプレイスクリプトが行き詰まっています。または、ゲームは正常に動作しますが、カメラ変換の不正確さから、ほとんどすべてが知覚できるほどの振動を持っていることがあります。

必要な精度のレベルがわかっている場合(たとえば、0.01単位のスパンは、通常の表示/相互作用距離で約1ピクセルにマップされ、小さいオフセットは表示されません)、上の表を使用して、それを失う場所を見つけることができます正確性を確保し、損失の多い操作の場合の安全性を数桁下げます。

しかし、もしあなたが巨大な距離を考えているなら、プレイヤーが動き回るときにあなたの世界をリセンタリングすることで、これらすべてを回避するほうが良いかもしれません。原点の周りに控えめに小さい正方形または立方体の領域を選択します。プレーヤーがこの領域の外側に移動するたびに、それらを変換し、世界のすべてのものをこの領域の幅の半分だけ戻し、プレーヤーを内側に保ちます。すべてが一緒に移動するため、プレーヤーには変化が見られません。不正確さは世界の遠く離れた場所でも発生する可能性がありますが、一般的には足元で発生するよりも目立ちにくく、プレイヤーの近くで常に高い精度が得られることが保証されています。


1
再センタリングは間違いなく行く方法です!
フローリス

2
固定小数点座標の使用はどうですか?必要に応じて64ビット整数を使用しますか?
APIビースト

問題は、再中心化された領域がどれくらい大きいかです。たとえば、ゲームで強いズームで遠距離で撮影したい場合、ダブルを使用する必要がありますか、それともフロートで十分ですか?クワッドツリーまたはタイルアルゴリズムに従って再センタリングする方が適切ではないでしょうか。
jokoon

レンダリングおよび物理システムで使用されるアルゴリズムの数値安定性に依存します。そのため、特定のコードベース/エンジンについて、確実に知る唯一の方法はテストシーンを試すことです。テーブルを使用して最大精度を推定することができます(たとえば、オブジェクトから16 km離れたカメラには、少なくともミリメートルのサイズのエラーが表示される傾向があるため、ズームはピクセルよりも小さいものを保持するのに十分な幅でなければなりません-ズームが必要な場合ゲームをよりタイトにするために2倍にするか、何らかの巧妙な計算が必要になる場合があります)が、この仮想制限のかなり前に、損失の多い操作のチェーンが問題に直面する可能性があります。
DMGregory

グラフィカルAPIの世界を新しくすることはどういう意味なのか、まだ疑問に思っています。インスタンス化された(またはインスタンス化されていない)ジオメトリの大きなチャンクがある場合、それを実行しても安全ですか?すべての変換を変換することを意味すると思いますが、これを数回行うと、浮動小数点の精度が失われるリスクはありませんか?
-jokoon

3

物理学の規模に依存するため、答えるのは困難です。ゼロに丸める必要のない許容最小移動速度はどれくらいですか?

大きな世界と一貫した物理学が必要な場合は、固定小数点クラスを使用することをお勧めします。

たとえば、世界中のどこからでもキャノンボールを撃つと同じ結果が得られ、64ビット固定小数点(32.32)を使用すると、ほとんどのゲームで認識できるものよりもはるかに高い精度が得られます。ユニットが1メートルの場合、原点から2147483km離れた232ピコメートルの精度で移動できます。

ローカルセル内の浮動小数点でローカル物理を実行して、プログラミング作業を節約し、市販の物理エンジンを使用できます。それはすべての実用的な目的のためにまだ合理的に一貫しています。

ボーナスとして、ブロードフェーズとAABBは、FPUの遅延により、固定小数点で高速になる傾向があります。また、単純なビットマスキングを実行できるため、固定小数点を八分木(または四分木)インデックスに変換する方が高速です。

これらの操作は、通常はFPUレイテンシーを隠すSIMD命令とパイプライン化からはあまり恩恵を受けません。

固定点でカメラの位置を差し引いてからすべてをレンダリングした後、位置を浮動小数点に変換し、大きな世界での浮動小数点の問題を回避し、浮動小数点を使用する通常のレンダラーを使用します。


-2

乗算することで完全に回避できます。
フロートを使用する代わりに、それらに10 ^(x)を掛けて保存し、必要なときに再度10 ^(-x)を掛けます。
それから、どのタイプのintを使用したいかに依存します。


1
これは問題を回避しません。固定小数点形式は依然として有限の精度と範囲を持っています-範囲が大きいほど精度は低くなります(その固定小数点を置く場所に基づいて)-「目に見える丸め誤差なしでレベルをどれだけ大きくできるか」の決定まだ適用されます。
DMGregory

3
さらに、10進数はあまり実用的ではありません。整数をビット単位で分割すると、固定小数点数の方がはるかに機能します(符号なし26.​​6を考慮してください-小数部は下位6ビット(1.0 / 64.0 * x&63)であり、整数部は単にx >> 6です) 。何かを10の累乗に上げるよりも、実装がはるかに簡単です。
アンドンM.コールマン
弊社のサイトを使用することにより、あなたは弊社のクッキーポリシーおよびプライバシーポリシーを読み、理解したものとみなされます。
Licensed under cc by-sa 3.0 with attribution required.