掲示板システム
ホーム
アクセス解析
カテゴリ
ログアウト
1.0365の2乗を正しく計算するには? (ID:147536)
名前
ホームページ(ブログ、Twitterなど)のURL (省略可)
本文
》ZENさん > ただし、これは結果をDoubleで評価しているのでしょう。 VB.NET で「a = b ^ c」という演算処理を行った場合、それは Dim w As Double = Math.Pow( Convert.ToDouble(b), Convert.ToDouble(c) ) Dim a As Decimal = New Decimal(w) に相当する処理に置き換えられます。 ヘルプにも、「^ 演算子」の演算結果は常に Double 値であると明記されていますね。 》ZENさん > 例えば、iがIntegerだとした場合、例えばi / 3という式だけを考えた場合、 > この式はDoubleで評価されるということを何かで見た覚えがあります。 i / 3 の演算結果は、基本的には Double 型で返される仕様です。ただし、 i が Single 型の場合は、結果も Single 型になりますし、 i が Decimal 型の場合は、結果も Decimal 型です。 詳細はヘルプの「/ 演算子」の項をご覧ください。 》Aoi さん > 掛け算と割り算はdecimalにキャストするようにしたいと思います 最初の回答で ZEN さんが既に書かれていますが、この場合、 「演算結果を Decimal に変換する」のではなく、演算処理を 「Decimal で演算されるような計算式」で行う必要があることに 注意してください。これは、演算結果が既に誤差を含んでいた場合、 後から Decimal に変換しても、誤差が消えるわけでは無いからです。 》Aoi さん > 加減算は大丈夫みたいですね 加減算の場合でも、「桁落ち誤差」や「情報落ち誤差」が発生する可能性はあります。 '-------------------- Dim a As Decimal, b As Decimal a = 0.0000000987654321D b = 1234567890000000D Dim x As Decimal, y As Decimal, z As Decimal x = 0D y = 0D z = 0D For i As Integer = 1 To 1000 x += a y += b z += (a + b) Next For i As Integer = 1 To 1000 x += b y += a Next MsgBox(x.ToString() & vbCrLf & y.ToString() & vbCrLf & z.ToString()) '-------------------- 上記は、a と b をそれぞれ 100 回ずつ足している処理です。 単純に考えれば、最終結果として予想される値は、 v = 1234567890000000000.0000987654321 なのですが、最終結果は Decimal の有効桁数を越えています。 実際に上記の処理を試してみると、結果が x = 1234567890000000000.0000987654 y = 1234567890000000000.0000988000 z = 1234567890000000000.0000987804 となっており、加算順序を変えるだけで最終結果が変化していることが分かります。 このような場合には、(x のように)値の小さい物から加算することで 誤差を抑えることができます。 》Aoi さん > 1.0365の2乗を計算したいのですが… > 1.07433225となるところが1.0743322499999999となってしまいます そもそも Double 型は、内部的には二進小数として管理される数値型です。 1÷3 の結果を、10進数では有限桁数で表現できない(3進数なら表現できる)のと同様、 1÷10の結果は、2進数では有限桁数で表現できない(10進数なら表現できる)。 そして 1.0365 という10進小数の場合、その2進表現は、 1.00001001010110000001000001100010010011011101001011110001101010011111101111100111011011001000101101000011 1001010110000001000001100010010011011101001011110001101010011111101111100111011011001000101101000011 1001010110000001000001100010010011011101001011110001101010011111101111100111011011001000101101000011 1001010110000001000001100010010011011101001011110001101010011111101111100111011011001000101101000011… のような循環小数となります。変数が保持できる桁数は有限ですから、 途中の桁で打ち切られて、「近似値」として扱われることになります。 ちなみに、1.0365 が Decimal として扱われた場合には、誤差なく格納できます。 概念的には 「整数 10635 の右から 4 桁目に小数点を打った値」のように管理されます。 そのため、Double/Single の場合のような誤差は生じません。 もちろん、1÷3 を格納するような場合は近似値になってしまいますけれどね。
←解決時は質問者本人がここをチェックしてください。
更新する
戻る
掲示板システム
Copyright 2021 Takeshi Okamoto All Rights Reserved.