System.Decimal
構造体は内部的に桁数の情報を持っている。
そのため、以下は異なる結果が返る。
Console.WriteLine(0m.ToString()); // 0
Console.WriteLine(0.0m.ToString()); // 0.0
この桁数を取得したい。
結論
結論としては以下のコードで取得可能。
int exponent = Decimal.GetBits(0.0m)[3] >> 16 & 0x00FF;
Console.WriteLine(exponent); // 1
仕組み
System.Decimal
構造体は次のように値を保持している。
Decimal.GetBits(decimal) メソッド を使用すると内部のバイナリデータを取得できるため、そこから取得する。
返ってくる System.Int32[]
配列の 0 ~ 2 は仮数部なので今回は無視。
// 4 要素の int 配列
int[] binary = Decimal.GetBits(0.0m);
// 添え字 0 ~ 2 は仮数部領域。添え字 3 の先頭 32 ビット領域が符号と指数部、そして未使用領域
int info = binary[3];
添え字 3 の数値に桁数(指数部)の情報が含まれるがそのままではダメで、未使用分のビットをずらす&符号情報を取り除く必要がある。
// 下位16ビットは未使用(全部ゼロ)なので捨てる
int signAndExponent = info >> 16;
さらに、最上位ビットが符号なのでこれを除外する。残りのビットは未使用領域でゼロなので 0x7FFF
を掛けてもよいが、今回は明示的に取得したいビット(下位8ビット)が残るように 0x00FF
を掛ける。
int exponent = signAndExponent & 0x00FF;