3

私のケースはゲームプロジェクトに関連しているので、この質問をGameDevに投稿することを検討しましたが、これはより広範なプログラミングSEに適していると思いました。結局、この質問をそこに投稿したほうがいいかどうか教えてください。

私の理解から-そして私が間違っている場合は訂正してください-モバイル向けのゲーム開発(私の場合)は、固定小数点計算を採用することでかなりの利益を得ることができます。デバイスが浮動小数点を適切に処理するための設備が整っていない場合。

ただし、固定小数点には制限があり、特にオーバーフローがあります。したがって、私の質問は、ターゲットプラットフォームを考慮して固定小数点が最良の代替手段であると判断した場合、特定のプロジェクトの要件がそれらの使用を許可するかどうかを判断する方法です。

わかりやすくするために、問題が発生しているコードを少し共有したいと思います。

CIwVec2 calculateBezier(float t, CIwVec2 p0, CIwVec2 p1, CIwVec2 p2) {
    float u = 1 - t;

    CIwVec2 p = IW_FIXED(u * u) * p0;   // (1 - t)²P0
    p += IW_FIXED(2 * u * t) * p1;      // 2(1 - t)tP1
    p += IW_FIXED(t * t) * p2;          // t²P2

    return p;
}

このプロジェクトでは、C ++を使用し、固定小数点数の独自の実装(16ビットと32ビットの両方があり、現在は32ビットを使用しています)とVectorクラスが付属するMarmaladeSDKを使用しています。 (CIwVec2)は、位置と計算にその実装を使用します(上記のコードに示されているスカラー乗法を含む)。ああ、IW_FIXEDは、浮動小数点数を固定小数点に変換するための単なるマクロです。

上記のコードを実行しようとすると、乗算オーバーフローエラーが発生します。次のように値をデバッグします。

t = 0
u = 1 (which converts to 4096 in int32 fixed-point with IW_FIXED)
p0.x = 1638400 (400.0f with IW_FIXED_TO_FLOAT)
p0.y = 409600 (100.0f with IW_FIXED_TO_FLOAT)

正直なところ、固定小数点数については完全には理解していません。私はその考えを理解していますが、固定小数点演算は私には完全には明確ではありません(基数2に関連するほとんどの数学のクラスを捨てたに違いありません)。しかし、1.0f * 400.0fのような単純なものが固定小数点のオーバーフローを引き起こすという事実に、私は完全に困惑しています。

したがって、プロジェクトで固定小数点をサポートすることに問題はないと思いましたが、そうではないようです。このゲームはトップダウンの自動車ゲームであり、巨大なトラックなどはありませんが、少なくともデバイスの画面と同じ大きさ(またはさらに良いのはその解像度)である必要があります。タブレットの場合も、1.0f * 400.0fのような問題があるということは、固定小数点が問題外であることを意味します。

私はこの仮定で正しいですか?そして、将来のプロジェクトや同様の問題を抱えている他の人々のために、プロジェクト内の固定小数点数の実行可能性をどのように評価できますか?また、16ビットと32ビットのどちらを選択するかは大きなボーナスになります:)

(長い投稿をお詫び申し上げます。お時間をいただきありがとうございます!)

アップデート:

したがって、これまでの回答を少しまとめてください。理想的なシナリオは、ニーズに必要な範囲を持つように固定小数点数を実装することです(Mooing Duckの回答)。また、32ビットの数値を使用する操作の場合、最も安全な方法は、64ビットを使用して計算することです(timdayの回答とMaxのコメント)。ちなみに、マーマレードにはいくつかの「安全な固定乗算」関数がありますが、CIwVec2のスカラー乗算演算子のオーバーロード(IW_FIXED_MUL下を使用し、安全に乗算されない)には当てはまりません。

そして最後に、私の特定のシナリオに関しては、マーマレード6.1の時点で、フロートを使用するだけがおそらく最良の解決策であるように思われます。

編集: マックスの答えは私の問題を本当に解決しましたが、それは主にマーマレードに固有のものだったためです。そのため、一般的に多くの人に役立つと思うので、MooingDuckの回答を選択しました。

4

3 に答える 3

2

固定小数点は、小数部の上半分を格納していると見なすことができます。この場合、下半分は4096です。したがって、1.0fは4096/4096に等しく、4096としてメモリに格納されます。詳細については説明しません。私はそれらを覚えていないので分数乗算のですが、重要な部分はA/D * B/D結果を得るために乗算するときですC/D、そして。CA*B/D

つまり、あなたが持っている場所では1.0f * 400.0f、コンピュータはこれをと見なします4096 * 1638400 / 4096。小さな代数は、これが1638400(400.0f)になるはずであることを示していますが、小数点ライブラリがそのために十分に賢くない場合、除算を行う前に一時的な値6710886400になります。これは、には大きすぎintます。

フローティングポイントの分母は4096であるため、「フロート」は最も近い0.00024まで正確であり、範囲は-524288.999f〜524287.999f(ish)です。コンパイラに「フロート」の精度を下げて範囲を広げる方法はありますか?そうでなければ、あなたは馬鹿にされています。

編集

Maxは、4096がMarmaladeの一部であり、変更できないことを確認します。その場合、いくつかのオプションが表示されます。
(1)固定小数点を使用しないでください。
(2)すべての浮動小数点数を-128から128の間に保つようにしてください。(3)スカラーとその下を使用
するaを乗算するための特殊関数を使用します。できれば、を特別なクラスでラップし、をオーバーロードして呼び出します。への暗黙の変換を提供しないでください。提供しないと、すべてのエラーが見つかりません。CIwVec2IW_FIXED_MULfloatoperator*IW_FIXED_MULfloat

于 2012-10-02T22:33:01.790 に答える
2

あなたが見ているものとそれが意味する32ビットの中間体(Mooing Duckの答えを参照)は、私には深刻な弱点のように思えます。

私は過去に固定小数点ライブラリを正常に使用しました(386/486時代のx86で)、それらはすべて、シフトを修正する前に乗算に64ビット中間体を使用しました(実際、Intelが非常に優れた32x32から64を提供したことを覚えているようです)これにぴったりのビット乗算命令)。中間精度が高いほど、データ範囲全体でかなりの自由度が得られます。このマーマレードライブラリのように制限されたもので作業するのは本当に嫌いですが、移植性の理由でなぜそれをしなければならなかったのかはわかります。

于 2012-10-02T22:44:23.790 に答える
0

9月にリリースされたMarmalade6.1Marmalade 6.1を使用する場合、今日のモバイル開発で固定小数点を使用することは意味がありません。

FPUを備えていないAndroidスマートフォンはほとんどありませんが、ほとんどのスマートフォンにはFPU、GLES 1.0およびGLES2.0を備えたGPUが搭載されています。現在、マーマレードを備えたGLES2.0デバイスを対象としています。

マーマレードにIW_FIXEDがある理由は、IwGXと呼ばれる独自のグラフィックレイヤーがあるためです。

2012年9月以前(マーマレード6.1)。IwGXは浮動小数点をサポートしていませんでした。そのため、開発者は最近のGLES 2.0デバイスをターゲットにしている場合でも、固定番号を使用する必要がありました。

今日、マーマレードで固定数を使用する利点はありません。

-

とにかく、それでも固定小数点で乗算したい場合は、IW_FIXED_MUL関数があります

追加:例のコードは正しいです。

于 2012-10-02T22:35:11.787 に答える