- PR -

Float→Doubleの型変換について(C#)

投稿者投稿内容
なちゃ
ぬし
会議室デビュー日: 2003/06/11
投稿数: 872
投稿日時: 2006-12-05 13:18
引用:

じゃんぬねっとさんの書き込み (2006-12-05 12:14) より:
浮動小数の誤差には疎い年代ですから、そう言われると不安になるのですが、
最終的に double 型に格納したいのであれば、という意味です。

確認せず書いているので、何か間違いがあるかもしれません。



Single→Doubleの変換は情報は失われない。
SingleやDoubleとDecimalの変換では、情報が失われる場合がある。

基数の違い、精度の違い、表現できる範囲の違いのためです。

DecimalはSingleやDoubleより表現できる桁数は多いが、表現できる値の範囲は狭い。
基数を変換すると、情報は失われる場合がある。

なので、まあ要するにわざわざDecimalを通して、情報を失わせる、
あるいはオーバーフローを起こす危険を冒していることになります。
じゃんぬねっと
ぬし
会議室デビュー日: 2004/12/22
投稿数: 7811
お住まい・勤務地: 愛知県名古屋市
投稿日時: 2006-12-05 13:59
コード:

    float   value1 = 123456.117F;
    decimal value2 = (decimal)value1;
    double  result = decimal.ToDouble(value2);


たぶん、こういうパターンだとダメっぽいですね。

_________________
C# と VB.NET の入門サイト
じゃんぬねっと日誌
むさいくろう
常連さん
会議室デビュー日: 2006/11/13
投稿数: 20
お住まい・勤務地: 本田市
投稿日時: 2006-12-05 14:11
こんなのではだめ?

float value1 = 123456.78F;
double value2 = (double)value1;
double value3 = System.Math.Round(value2, 2);
Console.Write(value3);


最初からdouble使えばいいと思うに僕も1票。
object
ぬし
会議室デビュー日: 2002/03/20
投稿数: 338
お住まい・勤務地: 香川県高松市
投稿日時: 2006-12-05 17:33
objectです。

今迄にも、何度か指摘して来たんですが、
同じ問題で堂々巡りをしている様です。

少し例を挙げて書きます。
float、doubleを使用するという事は、
「実数に対する処理をしていると考えるべき状況」
だと思います。

重要なのは、
「実数を一般的に直接表現するには、文字式の使用しかない」
という事実です。

つまり、実数を人間が
「数字(有限の数字で表現されたもの)として表現する」
場合、それは必ず
「有理数への丸め処理をしている事になる」
という事です。
#勿論、たまたま有理数になる場合もあります。
#しかし、実数を対象とする限り、その表現が有限の数列と一致する事は、一般的には殆ど有り得ない。
#何故なら、有理数は圧倒的に少ないから。(有理数は加算無限だが、実数は不加算無限)
#従って、実数を浮動小数として扱う限り、有効数字は絶対であり、本来丸め処理が必要になります。
#勿論、コンピュータ内での「二進数、有限数その他」表現上の問題もありますが。

たまに、
「実数を浮動小数点数すなわち有限桁数の2進数によって計算すると,どうしても誤差が生じる.
 それを丸め誤差という」
という記述をみますが、これは、2進数とは無関係に起きる話です。
#「コンピュータ内部での表現としての問題」と「実数自身が持つ問題」は区別すべき問題です。
#ここでの「丸め」という表現も少し変ですが、ここでは問題とはしません。

下図は、加算と乗算に関して、
1)「数だけ」を見て行った計算(普通学校で教えられる)
2)実数が有理数に丸められたと考えた場合の誤差を含んだ計算
です。
#1)は、本来「684.000+152.300+6.478」「58.360000*8.2540000」に対する計算処理だと思います。
コード:

1) ┃2)
684 ┃ 684.xxx
152.3 ┃ 152.3xx
+ 6.478 ┃+ 6.478
───── ┃─────
842.778 ┃ 842.xxx
━━━━━━╋━━━━━━━━━━━━
58.36 ┃ 5 8.3 6 x
* 8.254 ┃* 8.2 5 4 x
──────┃───────────
23344 ┃ 5x8x3x6xx2
2 9180 ┃ 2 3 3 4 4 4x
11 672 ┃ 2 9 1 8 0 5x
468 8 ┃ 1 1 6 7 2 2x
──────┃ 4 6 6 8 8 8x
481.70344 ┃───────────
┃ 4 8 1.7 x x x x x x
※*:乗算
※x:不明な数字、5x=5*x、x2=x*x


つまり、コンピュータ(その言語)の使用と関係無く、
誤差は、数(量)とその関係(計算)を通して伝播します。
従って、
その計算結果に対して、必ず「誤差伝播とその結果」を考慮した丸め処理が必要になります。
再度強調しますが、
これは、コンピュータとは関係無く「実数に対しては必ず必要な処理」です。

編集=======================================
Tdnr_Symさん、突っ込み有難う御座います。(^^ゞ
伝搬⇒伝播の間違いです。
※伝搬⇒伝播に修正
※文字⇒文字式、*=乗算⇒*:乗算

[ メッセージ編集済み 編集者: object 編集日時 2006-12-06 13:18 ]
Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2006-12-05 18:29
じゃんぬさん、お久しぶりです。

引用:

じゃんぬねっとさんの書き込み (2006-12-05 12:14) より:
引用:

Tdnr_Symさんの書き込み (2006-12-05 11:04) より:

float型の有効桁数は約7桁なので、それ以降の桁は無視すればいいのです。


ただ単に 「無視」 するだとまずいかもしれません。
1234.6 の時とか、結果が変わってしまうような...
("無視" の意味合いが違うかもしれませんが)



すいません。"無視"というのは"切捨て"をしろという意味ではないです。
1234.6のときansDは「1234.5999755859375」となりますが、
7桁の精度ということは、1234.599±0.005 程度の信頼性しかないですよとのことです。


引用:

objectさんの書き込み (2006-12-05 17:33) より:

つまり、コンピュータ(その言語)の使用と関係無く、
誤差は、数(量)とその関係(計算)を通して伝搬します。
従って、
その計算結果に対して、必ず「誤差伝搬とその結果」を考慮した丸め処理が必要になります。



細かいツッコミですが、「誤差の伝播(でんぱ)」では? ^^;
誤差-Wikipedia

「誤差の伝播」…なつかしい。
大学の物理実験を思い出します。「平均二乗誤差」を求めたりとか。
ぼのぼの
ぬし
会議室デビュー日: 2004/09/16
投稿数: 544
投稿日時: 2006-12-05 21:20
引用:

objectさんの書き込み (2006-12-05 17:33) より:
重要なのは、
「実数を一般的に直接表現するには、文字の使用しかない」
という事実です。


ここだけ読んで、ToStringとParseを使ってString経由で変換すれば良いのかと邪推してしまったり(^^;

doubleについては、このスレッドの甕星さんの説明が、個人的にはとてもわかりやすかったです。

引用:

原則として、同じ精度で値を扱うなら、double型のほうがdecimal型よりデータサイズも小さく演算も高速。科学技術計算では、そもそも入力値にも誤差があるので、有効桁数以下の細かな演算誤差は気にしない。だったら高速でデータサイズが小さいほうが有利。

もちろん財務計算など、そういった誤差が許されない場合もある。そこで生まれたのがDecimalのような二進化十進表現(BCD)。4bitで0〜9を表現し、10進数で計算を行うことで、人間が計算したときと同じ計算結果を得られる。

Tdnr_Sym
ぬし
会議室デビュー日: 2005/09/13
投稿数: 464
お住まい・勤務地: 明石・神戸
投稿日時: 2006-12-05 23:28
こんばんは。

引用:

もちろん財務計算など、そういった誤差が許されない場合もある。そこで生まれたのがDecimalのような二進化十進表現(BCD)。4bitで0〜9を表現し、10進数で計算を行うことで、人間が計算したときと同じ計算結果を得られる。



また細かいツッコミですが、.NETのDecimal構造体はBCD(二進化十進表現)ではないようですね。
Decimal構造体は、
flagsフィールドで、符号とスケールファクタを表し、
lo,mid,hiフィールドで96ビット整数を表しています。
# .NET ReflectorでDecimal構造体のソースコードを確認しました。

#BCDってメインフレームなんかで使われているんでしょうが
 私には、RTC(リアルタイムクロック)が日付・時刻データにBCDを使っているって
 こと以外あまり馴染みがないですねぇ。
MMX
ぬし
会議室デビュー日: 2001/10/26
投稿数: 861
投稿日時: 2006-12-06 11:25
二進化千進法で「格納」も 出てきます
Fall Microprocessor Forum 2006 - IBMが次世代サーバプロセッサPOWER6を発表
http://journal.mycom.co.jp/articles/2006/10/22/fpf1/002.html
10進浮動小数点演算器の実装により4〜7倍性能が向上するというデータを示した。
1桁10bit で格納、カンマ編集にいいかな ?

デシマルの種類
汎用機 COBOL COMP(packed decimal)、Java、.NET、POWER6
あたりでしょうか

スキルアップ/キャリアアップ(JOB@IT)