tmori3y2のブログ

主にWindowsのプログラムなど

Decimal型について

(2016/09/10 修正)

新人教育係を拝命した。

今回は、そのネタから一つ。

System.Decimal (decimal)は、

96bitの整数

0 ~ 79228162514264337593543950335 (296 - 1)

5bitの小数桁数

0 〜 28

1bitの符号

から構成される10進数小数型。

整数部、および、末尾の連続する0も含めた小数部の桁数の和が最大29桁、10進数で保持することが出来る。

小数桁数が0の場合は、絶対値が最大値を超える値はOverflowExceptionが発生し、それ以外では最上位から30桁目が銀行丸めで丸められる。

29桁の整数は、すべて表現できるわけではない。同じく、整数部1桁、小数部28桁の数をすべて表現できるわけではない。

絶対値が非零の最小値(10-28)を下回る場合は、OverflowExceptionではなく、上記の銀行丸めのルールに従い、0に丸められる。

ざっくりと表現するなら、

「0 ~ 79228162514264337593543950335 (296 - 1)の整数に、必ず整数桁が1桁以上、小数桁が0桁以上になるように小数点を打つ」

と言うとイメージが湧くと思う。

定義の通り、同じ1でも、1m、1.0m、1.00m,...でバイナリ表現が異なる。

バイナリ表現を一致させるには、Math.Round()で丸める桁を指定する必要がある。

小数部の0を切り詰める場合には、Math.Round()で丸めればバイナリ表現を一致させることが出来るが、0を増やしてバイナリ表現を一致させることは出来ない。

この辺、踏まえたテストメソッドがTestDecimal()である。

今回は、ChainingAssertionを使用している。

C++に慣れていると、System.Single (float), System.Double (double)をすぐに使いたがるが、10進数としては誤差があるので、10進数で誤差が出にくいSystem.Decimal (decimal)の方がGUIで丸め処理をする場合などに適している。数値演算速度の都合で内部的にはdoubleであっても、GUIでユーザ入力する場合、かつ、decimalで処理できる場合(Overflow/Underflowが発生しない場合)は迷わず使用することを検討してほしい。

(2016/09/10)

2016/09/10 AM時点で、はてなのMarkdownk記法の上付き・下付きが、PC版で逆になる現象が発生しています。

はてなに通報済み。