int
をカスタムフロートに変換しようとしています。ユーザーがexpと仮数に予約されているビット数を指定しますが、変換の仕組みがわかりません。私の関数はint値とint expを受け取り、数値(値* 2 ^ exp)を表します。つまり、値= 12、exp = 4は192を返します。しかし、これらを変更するために必要なプロセスがわかりません。私はこれを何日も見ていて、IEEEコンバーターのWebアプリで遊んでいましたが、正規化プロセスが何であるかを理解できません。 「2進小数点を移動して指数を調整する」ことがわかりましたが、これが何を意味するのかはわかりません。また、指数バイアスが何であるかわかりません。私が持っている唯一の情報は、あなたがあなたの指数に数を加えるだけであるということですが、私はその理由を理解していません。私は理解できる例をGoogleで検索してきましたが、これは私には意味がありません
浮動小数点数は、仮数の整数部を正確に1
に強制し、小数部を希望どおりにすると、正規化されます。
たとえば、2進数で13.25
である1101.01
を取得する場合、1101
は整数部、01
は小数部になります。
13.25
を1101.01*(2^0)
として表すこともできますが、整数部が1
ではないため、これは正規化されません。 ただし、指数を1増やすと、仮数を右に1桁シフトできます。
1101.01*(2^0)
= 110.101*(2^1)
= 11.0101*(2^2)
= 1.10101*(2^3)
この表現1.10101*(2^3)
は、13.25
の正規化された形式です。
そうは言っても、正規化された浮動小数点数は常に1.fffffff * (2^exp)
の形式になります。
効率を上げるために、1
整数部分をバイナリ表現自体に格納する手間を省き、そこにあるふりをしています。したがって、仮数用にカスタムメイドの浮動小数点型に5ビットを与えると、ビット10100
実際には1.10100
がわかります。
次に、標準の23ビットの仮数を使用した例を示します。
指数バイアスについては、標準の32ビットfloat
形式を見てみましょう。この形式は、1つの符号ビット、8つの指数ビット、23の仮数ビットに分かれています。
s eeeeeeee mmmmmmmmmmmmmmmmmmmmmmm
指数00000000
と11111111
には特別な目的(Inf
とNaN
を表すなど)があるため、たとえば2^1
から2^254
のように、8つの指数ビットで254の異なる指数を表すことができます。しかし、2^-3
を表現したい場合はどうでしょうか。どのようにして負の指数を得るのですか?
このフォーマットは、この問題を指数から127を自動的に引くで修正します。したがって:
0000 0001
は1 -127 = -126
になります0010 1101
は45 -127 = -82
になります0111 1111
は127-127 = 0
になります1001 0010
は136-127 = 9
になりますこれにより、指数範囲が2^1 ... 2^254
から2^-126 ... 2^+127
に変更され、負の指数を表すことができます。
「正規化プロセス」は、入力を選択範囲に変換します。
binary32 は、数値に最小の指数がない限り、仮数(仮数ではない)が_1.0 <= s < 2.0
_の範囲にあることを期待します。
例:
_value = 12, exp = 4
_は同じですvalue = 12/(2*2*2), exp = 4 + 3
_value = 1.5, exp = 7
_
仮数の先頭桁は常に_1
_であるため(数値に最小の指数がある場合を除く)、それを格納する必要はありません。また、指数を_7
_として保存するのではなく、127のバイアスが追加されます。
値= 10進1.5-> 1.1000 ... 000バイナリ-> 0.1000 ... 000格納バイナリ(合計23ビット)
exp = 7->バイアスexp 7 + 127-> 134 10進数-> 10000110バイナリ
格納されるバイナリパターンは、「符号」、「暗黙の先行1ビットの仮数」、および「バイアス指数」の連結です。
_0 10000110 1000...000 (1 + 8 + 23 = 32 bits)
_
バイアス指数が_0
_-最小値の場合、暗黙のビットは_0
_であり、_0.0
_のような小さな数値を格納できます。
バイアス指数が_255
_-最大値の場合、格納されたデータは有限数ではなく、「無限大」と「非数」を表します。
詳細については、参照先のリンクを確認してください。
トミー-chuxとeigenchrisは、他の人たちと一緒に優れた答えを提供しましたが、私があなたのコメントを正しく見ている場合、あなたはまだ「この情報をどのようにして使用するのですか?これは、ユーザーが指数のビット数を指定するカスタムfloat表現を作成する際に発生しますか?」気分を悪くしないでください。最初の数十回は泥が通り抜けるのは明らかです。私はそれを片付けるときに刺すことができると思います。
次のIEEE754-Single-Precision-Floating-Point表現に精通しています。
IEEE-754 Single Precision Floating Point Representation of (13.25)
0 1 0 0 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
|s| exp | mantissa |
1-bit sign-bit
、8-bit biased exponent
(8ビット超過127表記)、および残りの23-bit mantissa
。
ユーザーが指数のビット数を選択できるようにすると、ユーザーが選択した新しい制限で機能するために、rework指数表記にする必要があります。
何が変わりますか?
sign-bit
の処理を変更しますか-No。
mantissa
の処理を変更しますか-No(仮数/仮数を「隠しビット」形式に変換します)。
したがって、焦点を当てる必要があるのはexponent handling
だけです。
これにどのように取り組みますか?思い出してください、現在の8ビットの指数は、いわゆるexcess-127 notationです(127は、7
ビットの最大値を表し、現在の8-bit
制限内にバイアスを含めて表現できます。ユーザーが指数サイズとして6ビットを選択した場合、何をしますか?ユーザーの制限内で機能する新しいexcess-##表記を表す固定数を確保するには、同様の方法を提供する必要があります。
6-bit
ユーザー制限を使用すると、バイアスのない指数値の選択を31
(5-bits
で表すことができる最大値)として試すことができます。これに同じロジックを適用できます(上記の13.25の例を取ります)。数値のバイナリ表現は1101.01
であり、これに10進3 positions to the left
を移動して1.10101
を取得すると、3
の指数バイアスが得られます。
6-bit exponent
の場合は、3 + 31
を追加して、指数のexcess-31 notation
を取得し、100010
にした後、仮数を「隠しビット」形式で入力します(つまり、1
から先頭の1.10101
を削除して、新しいカスタムのトミー精度表現を作成します。
IEEE-754 Tommy Precision Floating Point Representation of (13.25)
0 1 0 0 0 1 0 1 0 1 0 1 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0 0
|- - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - -|
|s| exp | mantissa |
1-bit sign-bit
、6-bit biased exponent
(6ビット超過31表記)、および残りの25-bit mantissa
を使用します。
同じ規則が、上記の表記から浮動小数点数を戻すためにプロセスを逆にする場合にも適用されます。 (31
の代わりに127
を使用して、バイアスを指数から外します)
うまくいけば、これは何らかの形で役立ちます。ユーザーが選択した指数サイズを本当に許可する場合、他にできることはあまりありません。 IEEE-754標準は推測されたものではなく、多くの正当な理由とトレードオフが1-8-23の符号指数仮数レイアウトに到達することを覚えておいてください。しかし、あなたのエクササイズは基準をしっかりと理解することを要求する上で素晴らしい仕事をすると思います。
今、完全に失われ、この議論のnot addressedは、これがこのCustom Precision Floating Point Representation
で表すことができる数値の範囲に与える影響です。まだ見ていませんが、主な制限は、表現できるMAX/MIN
の削減にあるようです。
「コードでこれを行う方法」に投稿されたコメントに回答するには:(IEEEフロートであると想定)
A)IEEE浮動小数点数から符号なしの「指数」と「仮数」を抽出します。
私) exp = 0x7F800000 & yourFloatVar;
//フロートからビットb1からb8を取得します。 (b0は符号付きビット、b9は仮数です)
ii)exp = exp >> 23;
//右にシフトするため、この指数は右向きになります
iii)exp += 127;
//バイアスを追加(127は32ビットのみ)
iv)mantissa = 0x007FFFFF & yourFloatVar;
//フロートから最後の23ビットを取得
B)正規化
私)
while(true)
{
if( ((mantissa & 0xC0000000) != 0x80000000)
&&((mantissa & 0xC0000000) != 0x40000000) )
{
mantissa = mantissa << 1;
exponent--;
}
else //AKA the float has been normalized
{
break;
}
}
先頭の2ビットが「01」でも「10」でもない場合(これは2の補数の特性であり、正規化するための条件です)、仮数をシフトして指数をデクリメントします。
これは、これを行うための最も効率的なアルゴリズムではありません。手順を明確にしたかっただけです。私は何も見逃していないことを願っています!
仮数を正規化するには、小数点を左端のゼロ以外の数字の左側に配置します
例えば
10.11ベース2を正規化形式で表す
= 0.1011底2 * 2の2乗
2の底は2進数を使用しているためであり、+ ve 2のべき乗は小数点を2回左に移動したためです。マンティーザには4ビットのみが使用されることに注意してください
マンティッツァは1011になります