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

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

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

Re[1]: 演算誤差の処理について


(過去ログ 62 を表示中)

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

■36008 / inTopicNo.1)  演算誤差の処理について
  
□投稿者/ ダイ (1回)-(2009/05/18(Mon) 10:56:06)

分類:[VB.NET/VB2005 以降] 

http://cgi.2chan.net/m/res/34414.htm

4/5=1/a+1/b+1/c
a,b,cは整数

という問題を練習としてVB2005でやってみました。(初心者です)
解としては、順列ではなく組み合わせでOK、ということにします。

09/05/17(日)08:48:59 No.34422 において
-30 -6 1
-30 2 3
-10 -10 1
-5 2 2
-4 1 20
2 4 20
2 5 10
という書き込みがありますのでとりあえずこれを正解とします。

出力ウィンドウへの出力結果です*******************

Atype -030  -006   001  0   
Btype -030  -006   001  0.8   0
Atype -030   002   003  0   
Btype -030   002   003  0.8   0
Atype -010  -010   001  0   
Btype -010  -010   001  0.8   0
Atype -005   002   002  0   
Btype -005   002   002  0.8   0
Atype -004   001   020  0   
Btype -004   001   020  0.8   0
Atype  002   004   020  0   
Btype  002   004   020  0.8   0
Atype  002   005   010  0   
Btype  002   005   010  0.8   -1.11022302462516E-16

*****************ここまで出力結果

問題は最後に判定OKとなる計算のときの誤差です。
正解にあわせるために
f T < 0.800001 And T >= 0.799999 Then
という誤差範囲を設定することにしました。(数値はヤマカン)

質問としては、
1.上記判定文の「許容誤差」の適正値を決定する論理はありますか?
  #-1E-16という誤差を予想できるか?ということになると思いますが。
2.最後の解以外で誤差が発生しない理由は?
  2進数なら1/10でも循環小数になりそうな気がしますが・・・
3.今回の問題についてのプログラム(下記)の改善すべき点はどこでしょうか?
  #計算範囲を-1000から+1000にした時の処理時間の短縮に
  #ついても考えたいです。現在2-3秒かかっています。


Dim A As Integer
Dim B As Integer
Dim C As Integer
Dim T As Double
Dim R As Integer = 100
Me.Cursor = Cursors.WaitCursor
For A = -R To R
  If A <> 0 Then
    For B = -R To R
      If B <> 0 And A <= B Then
        For C = -R To R
          If C <> 0 And A <= C And B <= C Then
            T = 4 * A * B * C - 5 * A * B - 5 * B * C - 5 * A * C
            If T = 0 Then
              Debug.Write("Atype ")
              Debug.WriteLine(Format(A, " 000  ;-000  ") _
                            & Format(B, " 000  ;-000  ") _
                            & Format(C, " 000  ;-000  ") _
                            & T & "   " _
                            )
            End If
            T = 1 / A + 1 / B + 1 / C       '実数計算の判定式
            If T < 0.800001 And T >= 0.799999 Then
              Debug.Write("Btype ")
              Debug.WriteLine(Format(A, " 000  ;-000  ") _
                            & Format(B, " 000  ;-000  ") _
                            & Format(C, " 000  ;-000  ") _
                            & T & "   " _
                            & (T - CDbl(0.8)))
            End If
            My.Application.DoEvents()
          End If
        Next C
      End If
    Next B
  End If
Next A
Me.Cursor = Cursors.Default

引用返信 編集キー/
■36013 / inTopicNo.2)  Re[1]: 演算誤差の処理について
□投稿者/ ふるふる (25回)-(2009/05/18(Mon) 12:52:41)
No36008 (ダイ さん) に返信
> 質問としては、
> 1.上記判定文の「許容誤差」の適正値を決定する論理はありますか?
>   #-1E-16という誤差を予想できるか?ということになると思いますが。
 詳しくは知りませんが、あります。例えば有効桁数で小数点以下2桁までが有効だとすると、
1.23 という値は 1.225〜1.234999…という実際の値を取り得ます。乗除の計算があると
 例えば1.23*1.23は1.5129ですが、上記の可能性を考慮すると1.500625〜1.5252249999・・・
 という数値がありえます。1回の乗算で信用できる値は1.5まで、ということになり、
 有効桁数が1桁落ちます。
 

> 3.今回の問題についてのプログラム(下記)の改善すべき点はどこでしょうか?
>   #計算範囲を-1000から+1000にした時の処理時間の短縮に
 例えばBのループ内の条件で A<=B としています。A>Bの場合はループさせる必要がありませんね。
 Forループの終わりをAまでに出来ます。
 また実数同士の比較では、=を使わず、誤差を使うのが良いでしょう。
 IF R1=R2 THEN  というような場合、有効桁数がわかっていれば
IF ABS(R1-R2)<0.0000001 THEN
と書くようにしたほうが良いでしょう。なので
IF Abs(T-0.8)<0.0000001 Then
 としたほうが良いんじゃないかと思います。


引用返信 編集キー/


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

このトピックに書きこむ

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

管理者用

- Child Tree -