C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[2]: DecimalをIntegerに代入すると偶数丸めになる


(過去ログ 106 を表示中)

[トピック内 8 記事 (1 - 8 表示)]  << 0 >>

■63174 / inTopicNo.1)  DecimalをIntegerに代入すると偶数丸めになる
  
□投稿者/ Akiba (1回)-(2012/07/31(Tue) 03:44:51)

分類:[.NET 全般] 

お世話になります。
VB2010を使用していて最近気づきました。
Decimal形式の変数をInteger形式の変数に代入すると、小数点1桁目が偶数丸めになるようです。
これは仕様としてどこかに記述されている動作でしょうか?
偶数丸めは余り使う機会無いのですが、全く使わないこともないもので、もし仕様として明示されているのならSystem.Math.Roundの代わりに使ってみようかなと考えています。
ご存じの方おられれば教えていただけないでしょうか。


引用返信 編集キー/
■63175 / inTopicNo.2)  Re[1]: DecimalをIntegerに代入すると偶数丸めになる
□投稿者/ Azulean (6回)-(2012/07/31(Tue) 07:21:46)
No63174 (Akiba さん) に返信
> Decimal形式の変数をInteger形式の変数に代入すると、小数点1桁目が偶数丸めになるようです。
> これは仕様としてどこかに記述されている動作でしょうか?

この辺ですかね。
http://msdn.microsoft.com/ja-jp/library/06bkb8w2
> 小数に設定しようとすると、最も近い整数値に丸められます。
> 2 つの整数値に等しく近い場合は、最も近い偶数の整数に丸められます。

ただし、VB.NET の言語依存の仕様なので C# とは動作が異なります。
(Math.Round をあえて使った方が読み手の誤解を防ぐ効果を期待できます)
引用返信 編集キー/
■63176 / inTopicNo.3)  Re[2]: DecimalをIntegerに代入すると偶数丸めになる
□投稿者/ Akiba (2回)-(2012/07/31(Tue) 09:14:44)
No63175 (Azulean さん) に返信
> ■No63174 (Akiba さん) に返信

Azuleanさん、早速のご回答有難うございました。

> この辺ですかね。
> http://msdn.microsoft.com/ja-jp/library/06bkb8w2

Integer型の仕様だったんですね。

> ただし、VB.NET の言語依存の仕様なので C# とは動作が異なります。
> (Math.Round をあえて使った方が読み手の誤解を防ぐ効果を期待できます)

確かに。
偶数丸めにはSystem.Math.Roundを使った方がよさそうです。

しかし偶数丸めは余り使わないんですよね。
(鋼材の重量計算ぐらいしか使った記憶がありません。)
偶数丸めを使うケースを考えるよりも、意図せず偶数丸めになってしまうのを
防ぐことを考えた方が有益かもしれません。

それはさておき
明快なご説明、有難うございました。

解決済み
引用返信 編集キー/
■63177 / inTopicNo.4)  Re[2]: DecimalをIntegerに代入すると偶数丸めになる
□投稿者/ 魔界の仮面弁士 (11回)-(2012/07/31(Tue) 09:52:20)
No63174 (Akiba さん) に返信
> 偶数丸めは余り使う機会無いのですが、
ちなみに 2010 に限らず、旧VB(VBAを含む)でも整数への丸めには偶数丸めが採用されていたりします。
(IEEE 754 Section 4、JIS Z 8401 規則A・B も参照)

この最近接丸め方式は、IEEE 規格 754 の標準動作です。
http://ja.wikipedia.org/wiki/IEEE_754

四捨五入を選択したい場合には、
 Decimal.Round(Decimal, Int32, MidpointRounding) As Decimal
が使えます。
# Math.Round にも同等のメソッドがありますが、内部的には Decimal.Round を呼んでいるだけらしい…。


■No63175 (Azulean さん) に返信
>>Decimal形式の変数をInteger形式の変数に代入すると、小数点1桁目が偶数丸めになるようです。
> ただし、VB.NET の言語依存の仕様なので C# とは動作が異なります。

C# の動作は、C# 4.0 仕様書の 6.2.1 の項にて
》 decimal から整数型への変換では、変換前の値はゼロに向かって
》 最も近い整数値に丸められて、この整数値が変換の結果になります。
と示されていますね。

ちなみに、
 'Dim VB As Integer = decimalValue          '' VB / Option Strict Off
  Dim VB As Integer = CInt(decimalValue)    '' VB
  int CS = (int)decimalValue;               // C#
を比較してみたところ、それぞれ
 VB …… Convert.ToInt32(Decimal) As Int32
 CS …… Decimal.op_Explicit(Decimal) As Int32  (明示的型変換演算子)
が使われているようでした。

Convert.ToInt32 の方については、偶数丸めと明記されていましたが、
Decimal の明示的型変換演算子は、丸め方の記載が見当たりませんでした。

解決済み
引用返信 編集キー/
■63178 / inTopicNo.5)  Re[1]: DecimalをIntegerに代入すると偶数丸めになる
□投稿者/ shu (12回)-(2012/07/31(Tue) 12:17:34)
No63174 (Akiba さん) に返信

> Decimal形式の変数をInteger形式の変数に代入すると、小数点1桁目が偶数丸めになるようです。
これはOption Strict Onの状態だとエラーになるので止めたほうがよいと思います。
ちゃんとどのように変換するのか示してあげましょう。
引用返信 編集キー/
■63182 / inTopicNo.6)  Re[3]: DecimalをIntegerに代入すると偶数丸めになる
□投稿者/ Akiba (3回)-(2012/07/31(Tue) 13:03:23)
No63177 (魔界の仮面弁士 さん) に返信
> ■No63174 (Akiba さん) に返信

> ちなみに 2010 に限らず、旧VB(VBAを含む)でも整数への丸めには偶数丸めが採用されていたりします。

加減算を繰返した時、四捨五入より偶数丸めの方が誤差が少ないことが
期待できますので、偶数丸めが採用される理由はよく理解できますが、
問題は一般の人々に四捨五入は知っていても偶数丸めを知らない人
が多いことです。
計算結果をコンピュータの専門家だけが使うのなら問題はないのですが、
説明しても「難しい話はようわからん。」「四捨五入でいいよ。」と
言われておしまいです。
小学校で「偶数丸め」を言葉だけでも教えてもらえるような時代が来る
のを待つしかないのでしょうか。

> 四捨五入を選択したい場合には、
>  Decimal.Round(Decimal, Int32, MidpointRounding) As Decimal
> が使えます。

これは知りませんでした。
今までは自分で作った四捨五入の関数を使いまわしていましたが、
標準的なものがあるのなら今後は改めたいと思います。
参考になりました。

C#での詳しい説明も有難うございました。

解決済み
引用返信 編集キー/
■63183 / inTopicNo.7)  Re[2]: DecimalをIntegerに代入すると偶数丸めになる
□投稿者/ Akiba (4回)-(2012/07/31(Tue) 13:09:37)
No63178 (shu さん) に返信
> ■No63174 (Akiba さん) に返信
>
>>Decimal形式の変数をInteger形式の変数に代入すると、小数点1桁目が偶数丸めになるようです。
> これはOption Strict Onの状態だとエラーになるので止めたほうがよいと思います。
> ちゃんとどのように変換するのか示してあげましょう。

ご尤も。
止めたほうがよさそうですね。

解決済み
引用返信 編集キー/
■63185 / inTopicNo.8)  Re[4]: DecimalをIntegerに代入すると偶数丸めになる
□投稿者/ 魔界の仮面弁士 (12回)-(2012/07/31(Tue) 14:25:37)
No63182 (Akiba さん) に返信
> 計算結果をコンピュータの専門家だけが使うのなら問題はないのですが、
> 説明しても「難しい話はようわからん。」「四捨五入でいいよ。」と
> 言われておしまいです。

前者(わからない)はともかくとして、後者(四捨五入)と言われたのであれば
偶数丸めで実装する理由は無いですね。そこは対応が必要です。

まぁ、開発者でも偶数丸め(JIS丸め、Bankers' rounding)を知らない人はしばしば見かけますね。
丸め誤差、情報落ち、桁落ち、打ち切り誤差なども含め、面倒な個所ではあるのですが。


それは置いといて…0.5 の場合のみならず、いわゆる切り上げ/切り捨てについても、
マイナス値の丸め方(1.5→2 に丸める場合、-1.5は -1 にするか -2 にするか)とか、あるいは
有効数字の桁数未満の値の扱い(有効桁3桁の処理系において、途中の演算結果が 1.00000001 に
なったとき、これを整数に切り上げると時に 2 と見るか 1 と見るか)などがブレることがありますので、
「難しい話はようわからん。」と言われたからといっておしまいにせず、【具体例】を添えて
「この値の場合は、どちらの値に丸めますか?」などと聞き取っておく必要はあるかと思います。

それでも選べないユーザーには、同様の案件で他者が採用している方式を紹介して決めてもらうのも手。

設定画面等から丸め方式を後から変更できるように組み上げる事もできますが、
その場合でもどの丸め方式を初期値にしておくかは決めておかねばなりませんし。


> 小学校で「偶数丸め」を言葉だけでも教えてもらえるような時代が来る
> のを待つしかないのでしょうか。
概数は小4算数でしたっけか。四捨五入については、
 「一万の位で四捨五入」の場合、一万の位で四捨五入をする。
 「一万の位まで四捨五入」の場合、千の位で四捨五入をする。
の表現の違いが曖昧になっているユーザーも見かけますので御注意を。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -