1

32ビットIEEE754浮動小数点を符号付きQ19.12固定小数点形式に変換する必要があります。問題は、完全に決定論的な方法で実行する必要があることです。したがって、通常の(int)(f *(1 << FRACTION_SHIFT))は、非決定論的な浮動小数点演算を使用するため、適切ではありません。「ビットいじり」または同様の決定論的変換方法はありますか?

編集:この場合の決定論は次のように想定されます:同じ浮動小数点データが与えられた場合、異なるプラットフォームでまったく同じ変換結果が得られます。

4

3 に答える 3

3

浮動小数点は非決定論的ではありません。どこでそのばかげた仮説を立てましたか?

少し拡張する 1 << FRACTION_SHIFTと、正確に2の累乗になるため、浮動小数点で正確に表されます。正確な2の累乗による乗算は正確です(オーバーフロー/アンダーフローが発生しない限り、その場合はとにかく意味のある固定小数点表現がないため、気にしません)。したがって、可能な丸めの唯一のソースは、C#で完全に指定されている整数への変換です。したがって、結果が決定論的であるだけでなく、移植可能な同一の結果が得られます。

于 2012-07-18T13:44:39.850 に答える
3

@StephenCanonの答えは、この特定のケースが完全に決定論的であるということについては正しいかもしれませんが、私はより安全な側にとどまり、それでも手動で変換を行うことにしました。これは私が最終的に作成したコードです(これを行う方法についてのポインターを提供してくれた@CodesInChaosに感謝します):

public static Fixed FromFloatSafe(float f) {
    // Extract float bits
    uint fb = BitConverter.ToUInt32(BitConverter.GetBytes(f), 0);
    uint sign = (uint)((int)fb >> 31);
    uint exponent = (fb >> 23) & 0xFF;
    uint mantissa = (fb & 0x007FFFFF);

    // Check for Infinity, SNaN, QNaN
    if (exponent == 255) {
        throw new ArgumentException();
    // Add mantissa's assumed leading 1
    } else if (exponent != 0) {
        mantissa |= 0x800000;
    }

    // Mantissa with adjusted sign
    int raw = (int)((mantissa ^ sign) - sign);
    // Required float's radix point shift to convert to fixed point
    int shift = (int)exponent - 127 - FRACTION_SHIFT + 1;

    // Do the shifting and check for overflows
    if (shift > 30) {
        throw new OverflowException();
    } else if (shift > 0) {
        long ul = (long)raw << shift;
        if (ul > int.MaxValue) {
            throw new OverflowException();
        }
        if (ul < int.MinValue) {
            throw new OverflowException();
        }
        raw = (int)ul;
    } else {
        raw = raw >> -shift;
    }

    return Fixed.FromRaw(raw);
}
于 2012-07-19T15:03:23.957 に答える
1

決定論が絶対に必要な場合は、コンテンツを整数として解析し、手動で変換します。

まず、指数を抽出します。戻り値が小さすぎる場合0、大きすぎる場合は、オーバーフロー例外をスローします。

次に、符号と仮数を抽出します(暗黙の先頭を覚えておいて1ください)。符号ビットがの場合は1、仮数の符号を反転します。最後に、バイアスと組み合わせた指数によるビットシフトを実行します。

また、決定論を保証するソフトフロート実装も作成しました。かなり不完全ですが、必要な部分は実装されています。

于 2012-07-18T13:56:40.990 に答える