Decimal 数値のバイナリ表現は、1 ビットの符号、96 ビットの整数、および整数値を除算し、小数部を指定するために使用するスケール ファクタから構成されます。スケール ファクタは黙示的に数値 10 になり、0 から 28 の範囲の指数で累乗されます。Decimal.GetBits メソッドの戻り値はint[]でいまいち分かりにくいから確認用のコードを書いた(下手なコードだと思うけど良い方法を思いつけなかった)。
戻り値は、4 要素の 32 ビット符号付き整数配列です。
この配列の 1 ~ 3 番目の要素は、96 ビット整数の下位 32 ビット、中位 32 ビット、および上位 32 ビットをそれぞれ格納しています。
4 番目の要素は、スケール ファクタと符号を格納しています。この要素は、次に示す部分から構成されています。
ビット 0 ~ 15 の下位ワードは未使用で、0 である必要があります。
ビット 16 ~ 23 には、0 から 28 までの範囲の指数部を格納する必要があります。この指数部は、整数を除算する 10 の累乗を示します。
ビット 24 ~ 30 は未使用で、0 である必要があります。
ビット 31 は符号を格納している必要があります。0 は正、1 は負を表します。
ビット形式では負の 0 と正の 0 が区別されます。これらの値はすべての演算で等値として扱われます。
指数部が10の累乗なんだからSingle/Doubleとは違う分かりやすい値に変えた。
unsafe private static void PrintDecimal() { Func<Decimal, byte[]> toBytes = x => { var p = (byte*)&x; var bytes = new byte[sizeof(Decimal)]; for (var n = 0; n < bytes.Length; n++) bytes[n] = *p++; return bytes; }; WriteLine("Decimal:"); WriteLine("0.0M", toBytes(0.0M)); WriteLine("-0.0M", toBytes(-0.0M)); WriteLine("0.12M", toBytes(0.12M)); WriteLine("1.2M ", toBytes(1.2M)); WriteLine("12M ", toBytes(12M)); WriteLine("120M ", toBytes(120M)); WriteLine("1200M", toBytes(1200M)); WriteLine("-0.12M", toBytes(-0.12M)); WriteLine("-1.2M ", toBytes(-1.2M)); WriteLine("-12M ", toBytes(-12M)); WriteLine("-120M ", toBytes(-120M)); WriteLine("-1200M", toBytes(-1200M)); WriteLine("Decimal.MinValue", toBytes(Decimal.MinValue)); WriteLine("Decimal.MaxValue", toBytes(Decimal.MaxValue)); WriteLine(""); } private static void WriteLine(string value) { Console.WriteLine(value); } private static void WriteLine(string label, byte[] bytes) { Console.Write("{0}: 0x", label); var bs = (byte[])bytes.Clone(); Array.Reverse(bs); foreach (var x in bs) Console.Write("{0:X2}", x); Console.WriteLine(); }ksksts / junk / source — bitbucket.org
結果は次の通り。0.0Mと-0.0Mの指数部は1になるみたい。
Decimal: 0.0M: 0x00000000000000000000000000010000 -0.0M: 0x00000000000000000000000080010000 0.12M: 0x000000000000000C0000000000020000 1.2M : 0x000000000000000C0000000000010000 12M : 0x000000000000000C0000000000000000 120M : 0x00000000000000780000000000000000 1200M: 0x00000000000004B00000000000000000 -0.12M: 0x000000000000000C0000000080020000 -1.2M : 0x000000000000000C0000000080010000 -12M : 0x000000000000000C0000000080000000 -120M : 0x00000000000000780000000080000000 -1200M: 0x00000000000004B00000000080000000 Decimal.MinValue: 0xFFFFFFFFFFFFFFFFFFFFFFFF80000000 Decimal.MaxValue: 0xFFFFFFFFFFFFFFFFFFFFFFFF00000000
0 件のコメント:
コメントを投稿