- - PR -
490/4.9=99.99999
投稿者 | 投稿内容 | ||||
---|---|---|---|---|---|
|
投稿日時: 2005-11-20 12:14
最近は2進数のことが分からない人が多いのかもしれないですね。
昔はビット演算を使う機会が多かったから否応無しに勉強せざるを得なかったし、コンピューターといえばまず2進数の勉強から入ったものでしたが。 多くの方が指摘されているように、2進数、特に小数点以下の表し方を調べてみれば自ずと解決する問題だと思います。今後この仕事やっていく上でも知ってた方が何かと都合がいいと思います。 | ||||
|
投稿日時: 2005-11-20 12:33
こんにちは。
ちょっと拝見していて思ったのですが、有効数字の概念ってあまりやらないのでしょうか。 ( 小学生では「概数」ですかね ) 例えば、3.00 といえば 2.995〜3.005 の間、つまり0.005の誤差を含んだ、幅のある値と解釈しますから、キリの良い数字かどうかには拘らない、というものと思っていたのですけど。 ( キリの良い数字に拘るのは、あくまで表示上だけ ) だから、プログラムなんかでは、 double x = hoge(); if ( x == 3.0 ) …; なんてことはありえなくて、例えば double x = hoge(); if ( x > 3.0 - 0.0001 && x < 3.0 + 0.0001 ) …; のように、必ず何かしらの許容範囲をつけた判定をしますよね…。 | ||||
|
投稿日時: 2005-11-20 20:04
何か論点がずれてる。
siopさんのレスがないままじゃわからんけどさ。 わざわざ浮動小数点を自分で2進数にして表現してまで理解する必要ないよ。 2005-11-19 07:51の発言 > たまたま係数に4.9という数値を使ったから良かったのですが、 > 2進数で循環しない小数だと気付かなかったかも知れません。 とりあえず、 2進数で表現すると循環するので 途中で四捨五入(2進数なので0捨1入)するから正確ではない ということをわかったみたいだから、この話はこれで終わり。 もっと違うことを聞きたいんだよ。 それに > 例えば、3.00 といえば 2.995〜3.005 の間、つまり0.005の誤差を含んだ それじゃますますdoubleって使えねって思われるだけ。 | ||||
|
投稿日時: 2005-11-20 20:29
ご参考
http://www.microsoft.com/japan/msdn/library/default.asp?url=/japan/msdn/library/ja/vblr7/html/vagrpDataType.asp | ||||
|
投稿日時: 2005-11-20 20:39
いろいろとご意見、ありがとうございます。
今回問題となった現象について、いろいろと考えたのですが、端数処理に問題があったような気がします。 データ型がDoubleなのかDecimalなのかは問題ではなく、有効桁はどこまでで、端数をどうするのか。 実際のところ、プログラム内の小数点の掛け算や割り算では端数処理を行なっています。 どの桁(小数点第1位か第2位か、整数部1桁目かなど)でどうする(切り捨て、切り上げ、四捨五入など)のか。 今回、係数を使ってAをBに換算する処理は、どちらも「小数点第2位」で「切り捨て」を行なっていました。 そこが問題じゃないのかと。 A=100 K=4.9 (1).B=A*K=100*4.9=490.00000(端数処理にて490.0となる) (2).A=B/K=490/4.9=99.99999999999 (端数処理にて99.9となる) このような場合、(1)と(2)で同じ端数処理ではダメですね。 それじゃあ、(1)が切り捨てなら(2)は切り上げ? どちらも四捨五入なら問題ない? その辺が問題となってきます。 みなさんの、4.9を2進数に変換してみたら?という指摘を受けて、なんか違う方向に言ってるな〜と思ってたのですが、そういうことだったんです。 | ||||
|
投稿日時: 2005-11-20 21:10
490.00000もじつは若干490より大きい値のはず。
俺は面倒だからわざわざプログラムを書いて確認はしない。 (1)も(2)も誤差をもっている。 (1)は若干大きい、(2)は若干小さい。 でも、 たとえばある計算の真の答えが0.99999だとした場合、 その答えが出るまでに散々計算しまくって誤差が徐々に大きくなり 0.999995になってしまったら、5桁になるように 切り上げでは1.0になってしまい切捨てで0.99999となる。 0.999985になってしまったら、切り上げでは0.99999になってしまい 切捨てで0.99998となることも・・・・ そんなことはないか。 どうにもならないんじゃないの。 偶然切捨てで真の答えと等しくなっただけじゃないの。 0.5は0と1のちょうど間だから四捨五入じゃなくて、 50%の確率で0.5を切り捨てにすると良いって話もあるし。 オイオイ | ||||
|
投稿日時: 2005-11-20 21:19
プログラム書いて確認するのは私も面倒だからしませんが、
有効桁数小数点第二位ぐらいまでというなら、最初から100倍した値を持っていて、それで計算するという方法はどうでしょうか? もしくは計算するときに分母・分子共に100倍しておくとか。 100倍するときに小数部を四捨五入しておけば、第三位での四捨五入と同じかな。 490.0*100/4.90*100 という感じで。 ただ、分母の4.90*100を先に計算して、四捨五入して持たせておかないといけないと思いますが。 #すいません、これ、siopさまの求めている回答と違うかもしれません。 _________________ #「やらない」と「出来ない」を混同してはならない | ||||
|
投稿日時: 2005-11-20 21:27
有効桁がその程度なら四捨五入でいいんじゃないんですか? ※その「結果の値」何に使うのかによりますが。 っていうか何のために端数の処理をしてます?表示のため? |