Silverlight Toolkit の NumericUpDown, 0.1 + 0.1 + 0.1 + ...

昨日触れた NumericUpDown で気になるところが。Value (現在の値) と Increment (増分または減分する値) が double なんです。double って0.1を10回足しても 1 にならなかったり、n + 1 == n が真になったりするから怖い。何を言ってるのかわからねーと思うが(ry
実際に Increment を0.1にして10回クリックすると1.0になるので、コードを見てみるとこうなってました。

Value = (double)((decimal)Value + (decimal)Increment);

素直に decimal にすればよくね?(^^;
大丈夫そうな気がするけど、念のため double の中身をデコードしてビットを見てみます。

   1 0-01111111111(2^ 0)-1.0000000000000000000000000000000000000000000000000000
   1 0-01111111110(2^-1)-1.1111111111111111111111111111111111111111111111111111
   1 0-01111111111(2^ 0)-1.0000000000000000000000000000000000000000000000000000

読み方は、先頭の1が Console に double を表示した結果。おそらく ToString の結果。素直に値を表示してないんですね。面白いことになってきた!そして、ハイフン区切りで符号、指数部、仮数部。指数部は2の何乗という形で、仮数部は1以上2未満です。
1行目は「1.0」をデコードした結果。2行目は「0.1」を10回足した結果。あと一歩及ばず、おしいw 3行目は↑のいったん decimal に変換する方法で「0.1」を10回足した結果。これを見る限り、きれいな値になってます。

この形式の浮動小数点数では、0.1や0.2は循環小数になってしまいます。0.5はすっぱり1/2なのできれいに表せます。仮数部は1/2, 1/4, 1/8, ... と続いていきます。

 0.1 0-01111111011(2^-4)-1.1001100110011001100110011001100110011001100110011010
 0.2 0-01111111100(2^-3)-1.1001100110011001100110011001100110011001100110011010
 0.5 0-01111111110(2^-1)-1.0000000000000000000000000000000000000000000000000000

どうして decimal 使わないのかわからないけど、0〜100の範囲で0.1ずつ上下させるみたいな用途には問題なさげです。加速しないって別の問題があるけど(^^; だるい…