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

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

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

Re[48]: 四捨五入でバグ発見 [1]


(過去ログ 49 を表示中)

[トピック内 65 記事 (21 - 40 表示)]  << 0 | 1 | 2 | 3 >>

■26776 / inTopicNo.21)  Re[14]: 四捨五入でバグ発見
  
□投稿者/ なちゃ (184回)-(2008/10/20(Mon) 20:17:36)
現在は大抵10進型が用意されてるのでそれを使うのが普通ですね。
それで言えば、2進の少数型では10進少数を正確に表せない場合があるのは常識であり、
そのような場合に思った通りの結果が返らないことがあるのも常識です。
わざわさ書くまでもなく当たり前のことです。

しかしまあ最近ではそんなことは知らない人が使う事も多いですから、
そのことに触れておくのが親切だとは思いますが。

このような現象は少なくとも今はまだどこでもついて回ることが多いですから
最初に学んでおく方が無難だとは思います。

引用返信 編集キー/
■26777 / inTopicNo.22)  Re[14]: 四捨五入でバグ発見
□投稿者/ みきぬ (157回)-(2008/10/20(Mon) 20:34:35)
No26774 (ラウンドワン さん) に返信
> こういう場合は
> 「5万を加えて、10万で割り(int型のまま)、10万倍する」
> のが定石です。
>
> というのはどうなのでしょうか?
> 定石ということなのですが
>
それで何が言いたいの?

「元の数値が整数だから、できるだけ整数のままで計算を行う」というのが定石だとして、
このスレッドのお話はそうではない(元の数値が浮動小数点数)わけですが。
引用返信 編集キー/
■26780 / inTopicNo.23)  Re[15]: 四捨五入でバグ発見
□投稿者/ ま (140回)-(2008/10/21(Tue) 00:21:34)
>「元の数値が整数だから、できるだけ整数のままで計算を行う」というのが定石だとして、

違う。元の数値は浮動小数点数です。10万倍してどーたらこーたらってのは。
有限桁数内の演算誤差を無くすため定石です。昔はCPUの実数演算機能が極めて
遅かったってのもあるのですけど、

3.14159 + 2.3456 * 1.215 => 各値に10万掛けて long に格納する(小数点以下切捨て)。
314159 + 234560 * 121500 => 結果を double に格納して 10万で割る。
念のため 小数点第6桁を切り落とす。

又は、
結果を正数割り算で10万で割り、余りを5桁の0サプレスして答えと "." 連結する。


>というわけで答えを直接書かずに探して味噌、と書いておく。

この含みのある回答の答えの1つが、整数演算。
パック10進数とかBCD演算もそうです。



引用返信 編集キー/
■26781 / inTopicNo.24)  Re[16]: 四捨五入でバグ発見
□投稿者/ なちゃ (185回)-(2008/10/21(Tue) 02:18:51)
ところで今回の話とは別ですが、この計算に
Math.Pow
を使うことに微妙に不安を感じたりします。

あと有効桁数って言い方は変かな

引用返信 編集キー/
■26786 / inTopicNo.25)  Re[17]: 四捨五入でバグ発見
□投稿者/ みきぬ (158回)-(2008/10/21(Tue) 10:17:05)
No26781 (なちゃ さん) に返信
> ところで今回の話とは別ですが、この計算に
> Math.Pow
> を使うことに微妙に不安を感じたりします。
>
よくわからなかったのですが、どういった不安ですか?
それとも、ほかに Math.Round() のかわりになる安全な方法があるということですか?

引用返信 編集キー/
■26842 / inTopicNo.26)  Re[18]: 四捨五入でバグ発見
□投稿者/ ラウンドワン (6回)-(2008/10/22(Wed) 06:19:20)
doubleを使った場合に近似値で処理されるのがしょうがないというのが
プログラマーの常識ということを知れたのは勉強になりましたが

下記プログラムののdoubleをdecimalに修正すれば、正常に動作するみたいなのですが
なぜdoubleを使っているのでしょうか
これには、何か理由があるのでしょうか。



Public Shared Function ToHalfAdjust(ByVal dValue As Double, ByVal iDigits As Integer) As Double
Dim dCoef As Double = System.Math.Pow(10, iDigits)

If dValue > 0 Then
Return System.Math.Floor ((dValue * dCoef) + 0.5) / dCoef
Else
Return System.Math.Ceiling((dValue * dCoef) - 0.5) / dCoef
End If
End Function



引用返信 編集キー/
■26843 / inTopicNo.27)  Re[19]: 四捨五入でバグ発見
□投稿者/ Jitta on the way (195回)-(2008/10/22(Wed) 07:44:55)
No26842 (ラウンドワン さん) に返信
> doubleを使った場合に近似値で処理されるのがしょうがないというのが
> プログラマーの常識ということを知れたのは勉強になりましたが
>
> 下記プログラムののdoubleをdecimalに修正すれば、正常に動作するみたいなのですが
> なぜdoubleを使っているのでしょうか
> これには、何か理由があるのでしょうか。
そんな単純じゃないよ。プログラムで扱う、リテラルも含んだ全ての数値を decimal にしないと、double になったとたんに発症する。
希望する桁の1つ下を四捨五入してから、希望する桁を処理するのがいいかな?

-----

それはともかく。小数点以下3桁でもう信頼性がなくなるんだっけ?IEEE フォーマットって、2進化してから小数点移してますよね?0.555555*10^3 じゃなく、0.100010101110001…*2^10 でしたよね?仮数部は53桁あるけど、溢れのマルメが小さい方向に向かうのかな?
引用返信 編集キー/
■26845 / inTopicNo.28)  Re[20]: 四捨五入でバグ発見
□投稿者/ 774RR (230回)-(2008/10/22(Wed) 08:54:04)
演算速度というものがあるわけだ。
decimal の演算速度は double の演算速度よりも比較にならないくらい遅い。
その必要がない限り double を使うほうが適切だと判断できる。

そもそも工学的応用では有効数字っつー概念があるわけだ。
有効数字よりも長い桁数で計算するのは無駄な場合が多い。
double で精度落ちする桁数は、たいていの応用例での有効数字桁数よりも多いので
工学的応用では double のほうが有益。
555.555 が 555.55499999... であっても問題ない応用では double を使うべき。
そもそも double では 555.56 も表現できず 555.559999999999945 なんだぜ。

経済学的金融的応用では全桁が全部有効数字ということで工学応用とは前提条件が違う。
555.555 が 555.55499999... では困るのであれば double は使ってはならない。
decimal であるとか、固定小数点数とか、そういうのを使う必要がある。
あ、答え自分で書いちゃったな・・・
引用返信 編集キー/
■26846 / inTopicNo.29)  Re[11]: 四捨五入でバグ発見
□投稿者/ ふるふる (17回)-(2008/10/22(Wed) 09:22:09)
答えはでてしまっているのでちょっとした疑問なんですが。

No26770 (f_yamaki さん) の投稿で、
>
> 情報処理の数値計算系の入門書にも出ていると思いますが、計算上の有効桁を
> 考慮して、”十分小さな値を加える”方法は広く使われています。
> (774RRさんの仰るとおり、この”十分”がまた面倒な事ではありますが)

この「十分小さな値」とはどうやって求めるんでしょうか。
私が理解しているのは、四捨五入が必要なときは、計算の一番最後に行う。というもので、
最後の四捨五入をするときに、有効桁+1桁大きい桁数で小さい値(有効桁が小数点以下3桁ならば小数点以下4桁の数値で小さい値、すなわち0.0001)を使いましょう、というものですけど。
そこで四捨五入を一番最後に持ってくるために計算方法をちょっと変えてやったりとか。



引用返信 編集キー/
■26847 / inTopicNo.30)  Re[11]: 四捨五入でバグ発見
□投稿者/ ふるふる (19回)-(2008/10/22(Wed) 09:27:45)
2008/10/22(Wed) 09:29:23 編集(投稿者)
2008/10/22(Wed) 09:29:15 編集(投稿者)
2008/10/22(Wed) 09:29:09 編集(投稿者)

内容重複により削除します。

引用返信 編集キー/
■26864 / inTopicNo.31)  Re[21]: 四捨五入でバグ発見
□投稿者/ Jitta (525回)-(2008/10/22(Wed) 12:08:43)
No26845 (774RR さん) に返信
> 演算速度というものがあるわけだ。
> decimal の演算速度は double の演算速度よりも比較にならないくらい遅い。
> その必要がない限り double を使うほうが適切だと判断できる。

メモリ消費量も。double は64ビット。decimal は128ビット。
とか話をすると、「過去からの継承」という話になるかも。
double なら、32ビットレジスタ2つでまかなえる。けれども、decimal は4つも必要になる。
あるいは、2回に分けて演算しなければならない。
今でこそ32ビット全盛だけど、16ビットや8ビット全盛だった頃に decimal が用意できたとは思えない。
昔から、「FOR I = 0.1 TO 10 STEP 0.1」(N60-BASIC)は止まらないことで有名。


過去の話題
http://www.atmarkit.co.jp/bbs/phpBB/viewtopic.php?topic=26141&forum=7&67
http://blogs.wankuma.com/jitta/archive/2005/11/22/19516.aspx
引用返信 編集キー/
■26867 / inTopicNo.32)  Re[21]: 四捨五入でバグ発見
□投稿者/ ラウンドワン (7回)-(2008/10/22(Wed) 12:38:18)
> 演算速度というものがあるわけだ。
> decimal の演算速度は double の演算速度よりも比較にならないくらい遅い。
> その必要がない限り double を使うほうが適切だと判断できる。

プロジェクトのコストを考えると
速度的な問題が出てくるまではdecimalを使うほうが適切な気がするというのは
ど素人の発想かもしれませんが

>固定小数点数とか
固定少数はvb.netにはないようなのですが
少数以下2桁程度までの計算でよければ
整数型が一番速いのなら、すべて整数integerに直して計算するのが
一番早いって思えてくるんですが、そういうことなんですか?


引用返信 編集キー/
■26868 / inTopicNo.33)  Re[22]: 四捨五入でバグ発見
□投稿者/ 774RR (231回)-(2008/10/22(Wed) 13:05:30)
プロジェクトのコスト、って何? 適切って何に対して適切の意図なの?

「適切」であるとは要件定義次第。
0.3333333333333 + 0.3333333333333 + 0.3333333333333 = 0.9999999999999 であるべきなのか?
それとも 1/3 + 1/3 + 1/3 のつもりであったが桁数が足らないだけだったので 1 であるべきなのか?
この辺は応用側から出てくる要望次第なので、要件が決まらないと決定できない。

固定小数点数を使うのが適切なのか?
double を使うのが適切なのか?
decimal を使うのが適切なのか?
最初からこれだ!と決め打ちするなどありえない。すべては要件次第。

> 少数以下2桁程度までの計算でよければ
# 少数では意味が違う。小数点以下であるものとして以下検討
3桁目以後の扱いはどうあるべきなのか?(乗除算すると小数点下3桁目以後が必ず発生する)
整数部として必要な数値の範囲はどうなのか?(乗除算の途中で整数型範囲をあふれる可能性まで要考慮)
その辺がクリアになっているのであれば、実値の100倍値を整数型に保持して演算する、ってのはあり。
実際、俺たちが組み込み用途で「マイコン」を使う場合にはそうしている。

引用返信 編集キー/
■26917 / inTopicNo.34)  Re[23]: 四捨五入でバグ発見
□投稿者/ ラウンドワン (8回)-(2008/10/22(Wed) 20:38:47)
> プロジェクトのコスト、って何? 適切って何に対して適切の意図なの?

もちろん要件によると思うのですが
成果物は作品ではありませんから、最適化されたプログラミングは要求されていないと思うんですよ
速度的に問題が出ない限りはデメリットはないでしょう?
デメリットがないのなら、最初からdecimalにしたほうがよくないですか?
少なくとも、decimalには安定性の向上とバグ発生時の修正の手間がかからないというメリットがあると思います

> その辺がクリアになっているのであれば、実値の100倍値を整数型に保持して演算する、ってのはあり。

ということは、内部計算がdoubleになってるとはいえ
使う変数の定義は
整数型>double>decimal
の順で計算速度は速いということなんですね


引用返信 編集キー/
■26919 / inTopicNo.35)  Re[24]: 四捨五入でバグ発見
□投稿者/ なちゃ (187回)-(2008/10/22(Wed) 22:16:52)
どうも誤解があると思うのですが、

>デメリットがないのなら、最初からdecimalにしたほうがよくないですか?
>少なくとも、decimalには安定性の向上とバグ発生時の修正の手間がかからないというメリットがあると思います

あなたの用途にとってはそうであっても、そうでない用途もあるわけで、何度も目的によるといわれているとおり、
「あなたのプロジェクトにとってdoubleが最適」といっているのではありません。
あなたの周囲ではdecimalのメリットがデメリットより大きいんでしょう。

しかし、すべての人にとってdoubleがdecimalよりも「危ない」わけじゃないというのも分かりますよね?

decimalのデメリットが許容できない場合もあるわけです。
プロジェクトによっては、doubleの動作ではまるなどあり得なくて、効率の悪いdecimalを使うなど論外ということもあり得ます。
そもそも目的上double使うのが当たり前で、そんなところにdecimalを使っては成果物の価値を大きく下げてしまう世界だってあるわけです。

doubleの特徴をほとんど分かっていない人ばかりのプロジェクトでは、特に理由がなければdecimalという判断もあるでしょう。

あと、

>整数型>double>decimal
>の順で計算速度は速いということなんですね

どうも何でも唯一の正解を求めているようですが、必ずしも一概に言い切れるものではありません。

引用返信 編集キー/
■26920 / inTopicNo.36)  Re[25]: 四捨五入でバグ発見
□投稿者/ ラウンドワン (9回)-(2008/10/22(Wed) 22:50:00)
確かに金額を扱わなくて、四捨五入が重要でない限りはdoubleで十分ってのは理解できます
ただ

>doubleの特徴をほとんど分かっていない人ばかりのプロジェクトでは、特に理由がなければdecimalという判断もあるでしょう。

これについては
私のような「doubleの特徴をほとんど分かっていない人」が一人でも
プロジェクトに混ざっているかもしれない「会社やグループ」の場合は
ソフトによらず標準としてdecimalでも良いのではないかとおもったりしてます
ていうかプロの世界には私のような無知はいないんでしょうね

>どうも何でも唯一の正解を求めているようですが

例外を言い出すときりがないと思いますが
一般論としても違うということですか?

引用返信 編集キー/
■26921 / inTopicNo.37)  Re[26]: 四捨五入でバグ発見
□投稿者/ なちゃ (188回)-(2008/10/22(Wed) 23:19:16)
No26920 (ラウンドワン さん) に返信
> 私のような「doubleの特徴をほとんど分かっていない人」が一人でも
> プロジェクトに混ざっているかもしれない「会社やグループ」の場合は
> ソフトによらず標準としてdecimalでも良いのではないかとおもったりしてます

うーん、なんでそこにこだわるのか…
一般論として、ソフトによらずこうだってことは言えないでしょう?
decimalのデメリットが問題ないソフトしか作成しないのであればそれはひとつの判断として間違ってはいないでしょうし、
いろんなソフトを作るところなら、プロジェクトによって変えないといけない可能性もあるでしょう。

そういうところがどうも唯一の正解を求めたがってるって風に感じるんですね。


> >どうも何でも唯一の正解を求めているようですが
>
> 例外を言い出すときりがないと思いますが
> 一般論としても違うということですか?

100倍して整数型で計算てのは、掛け算や割り算では補正がいるってことです。
計算途中に数学関数の計算がいるなら途中で部分的にdoubleを使わないといけないこともあるってことです。
もちろんないかもしれません。

変換や補正を行うことに比べて、ハードでの浮動小数点演算は高速かもしれません。

まあ、いらん処理が入らない前提であれば、多くのCPUではこの順になるのではないかとは思いますけどね。
※浮動少数の演算速度が今現在どの程度かは全然把握してないので、実は整数と変わらないかもしれません。
 多数の浮動小数点ユニットを搭載していて、浮動少数の方がトータルでは速いCPUもあるかもしれません。

引用返信 編集キー/
■26923 / inTopicNo.38)  Re[26]: 四捨五入でバグ発見
□投稿者/ よねKEN (15回)-(2008/10/22(Wed) 23:36:19)
極端な言い方をすれば、
いわゆる業務系アプリ(金額を扱うことを前提とするアプリと定義します)を対象するならば、Decimalで十分です。
科学技術系アプリ(実験的に得られる値を主に使うアプリと定義します)を対象とするならば、Doubleで十分です。

コンピュータは元々軍事上の計算、特に、弾道計算を行うために開発されました。
そのために使用する数値型としては浮動小数点数が最適だったわけで、
その延長線上にあるのがSingleやDoubleです。その後、いろいろな用途に使われるようになり、
それ以外の型も考案されました。

実験/実測から得られた値にはもともとある程度の誤差があり、
その誤差の範囲(つまり有効桁数の範囲)では正確さは最も重要ではありません。
この発想の元にある数値型が浮動小数点数です。

引用返信 編集キー/
■26925 / inTopicNo.39)  Re[27]: 四捨五入でバグ発見
□投稿者/ 出水 (91回)-(2008/10/22(Wed) 23:54:46)
ちょうど今売っている数学セミナー11月号が浮動小数点の誤差の話題でした
要は、正負で判定するべき個所で、厳密な計算なら正なのに
誤差の蓄積のせいで負と判定されるのを回避するにはどうするか、って話なのですが…

しっかり理解できないぐらい難解な書き方してたので、誰か解読Plz(w
引用返信 編集キー/
■26931 / inTopicNo.40)  Re[28]: 四捨五入でバグ発見
 
□投稿者/ みきぬ (170回)-(2008/10/23(Thu) 09:39:14)
2008/10/23(Thu) 14:45:40 編集(投稿者)
2008/10/23(Thu) 09:46:25 編集(投稿者)
2008/10/23(Thu) 09:41:05 編集(投稿者)

本題とは関係ないけど、 No26786 の疑問に対してどなたか解説してくれるとうれしいかなぁ、なんて思ったり。

疑問の理由:
Visual Studio 2003 で四捨五入するメソッドを作れと言われたら自作するしかなくて、その方法はたぶん同じようなもの(尤もパラメータは decimal にすると思うけど)になると思ってるんですが、そのときに Math.Pow() がだめって言われてしまうと非常に困ってしまうわけなんですが。

# もしかして 10 ^ x て書けばおっけー? でもこれ C# だと使えないしなぁ。

-----
あれ、リンクにならない。…なんでだろ?
-----
教えてもらったので実践(。。;
引用返信 編集キー/

<前の20件 | 次の20件>
トピック内ページ移動 / << 0 | 1 | 2 | 3 >>

管理者用

- Child Tree -