28

この質問を言い換える別の方法はfloat、0 と 1 の間にある a を使用して、小数点以下の何桁に移動できるかということだと思います。

MSDNを見て解決しようとしました。つまり、精度は 7 桁です。の変更しか追跡できないという意味だと思いました0.0000001

しかし、もしそうなら:

float test = 0.00000000000000000000000000000000000000000001f;
Console.WriteLine(test);

それは書き出す9.949219E-44

さらにゼロを追加すると、出力されます0

その程度の精度は非常に間違っているように見えるので、ここで何かが欠けていると確信しています。主に float のサイズは 32 ビットであり、その精度レベルでの 0-1 には 1e+44 の可能な数値が含まれます...

4

5 に答える 5

31

標準浮動小数点数の 0 と 1 の間の一意の値はいくつありますか?

これは実際にはあなたが答えたい質問ではありませんが、答えは、01自体を含めずに、この範囲に2**23 - 1非正規数と126 * 2**23正規数があり、合計で127 * 2**23 - 1、または1,065,353,215です。

ただし、これらの数値はとの間の間隔で均等に分布していないことに注意してください。from toループでの「デルタ」を使用してもうまくいきません。011f / 1065353215f0f1f

0.00...01 の (10 進数) 形式の等しい長さのステップで 0.0 から 1.0 にステップしたい場合は、decimal代わりに を使用する必要がありfloatます。そのような数値を正確に表します。

に固執する場合は、 (提案された値の 10 倍)floatを試してください。0.000001

また、注意:float . たとえば、値0.000986fまたは変数0.000987fに保存してみてくださいfloat(最適化によって値が「より広い」ストレージの場所に保持されないようにしてください)、その変数を書き出します。最初の 7 桁は0.0009860000resp と同じではありません。0.0009870000. ここでもdecimal、10 進展開が「短い」数値で作業したい場合に使用できます。

編集:ループに「バイナリ」ステップを使用できる場合は、次を試してください。

float delta = (float)Math.Pow(2, -24);

または同等のリテラルとして:

const float delta = 5.96046448e-8f;

このデルタの良いところは、ループを介して遭遇するすべての値が で正確に表現できることfloatです。の直前 (下)1fでは、そのマグニチュードで可能な限り短いステップを踏むことになります。

于 2013-07-30T15:19:55.723 に答える
18

これは有効数字 7です。つまり、指数表記で記述する場合、指数は無視されます。

0.000000000000000001234567 の有効桁数は 12345670000000000000 と同じですが、指数が異なります。これが、浮動小数点数が非常に小さな数値と非常に大きな数値を格納できるようにする魔法です。

(0, 1)の a に可能な数が正確にいくつあるかについては、float今のところ正確には言えません。仮数は 23 ビットなので、2 23の状態が考えられます。次に、8ビットの指数があり、私がひどく間違っていなければ、可能な値の約半分が0と1の間の数値になります.これにより、その範囲に約2 23 + 7 = 2 30の可能な値が残るはずです. . おそらく上限であり、正確な値ではありません。正確に知るには、より細かい詳細についてのドキュメントを参照する必要があります (おそらく、上記の数学を再考して、いくつかの点を見逃す可能性があります)。

于 2013-07-30T14:30:20.690 に答える