tagCANDY CGI VBレスキュー(花ちゃん) の Visual Basic 2010 用 掲示板(VB.NET 掲示板) [ツリー表示へ]   [Home]
一括表示(VB.NET VB2005)
タイトルVB2005の倍精度計算精度は?
記事No8273
投稿日: 2008/10/04(Sat) 22:48
投稿者chime
VB6の計算をVB2005に移植中ですが、計算精度に疑問がでました。
VB6では
Visible = True
Dim sj1 As Double, sj2 As Double, sj3 As Double
Dim x As Double
Dim n As Integer, i As Integer
Dim sj(500) As Double
        n = 14
        sj3 = 0
        sj2 = 0.00001
        x = 2.40482555769577
        For i = 1 To n - 1
            sj1 = 2# * (n - i) * sj2 / x - sj3
            sj3 = sj2
            sj2 = sj1
        Next i
         Print sj1
で、答えが8.32489632784927E-12です。
VB2005では
     Visible = True
        Dim sj1, sj2, sj3, x As Double
        Dim n, i As Integer
        Dim sj(500) As Double
        n = 14
        sj3 = 0
        sj2 = 0.00001
        x = 2.40482555769577
        For i = 1 To n - 1
            sj1 = 2.0# * (n - i) * sj2 / x - sj3
            sj3 = sj2
            sj2 = sj1
        Next i
        Label1.Text = CStr(sj1)
で答えは8.18545231595635E-12
と計算結果が異なります。さらにsj2=1.0E-10から始めると
sj1の答えは値が5桁小さくなりますが、VB6とVB2005では3倍程度結果が異なります。

まだ、どちらの計算が正しいかの検討はしてはいませんが、厄介なことになりそうです。

chime

[ツリー表示へ]
タイトルRe: VB2005の倍精度計算精度は?
記事No8279
投稿日: 2008/10/05(Sun) 19:32
投稿者花ちゃん
>             sj1 = 2# * (n - i) * sj2 / x - sj3


              sj1 = 2# * (n - i) * sj2 / (x - sj3)

で計算したらどうなりますか?

[ツリー表示へ]
タイトルRe^2: VB2005の倍精度計算精度は?
記事No8282
投稿日: 2008/10/05(Sun) 21:17
投稿者chime
> >             sj1 = 2# * (n - i) * sj2 / x - sj3
>
>
>               sj1 = 2# * (n - i) * sj2 / (x - sj3)
>
> で計算したらどうなりますか?

コメントありがとうございます。

計算式は2項の差であり、ご指摘いただいた括弧で括って1項にすることはできません。

chime

  

[ツリー表示へ]
タイトルVB6.0の方が正しく計算できていない(再投稿)
記事No8285
投稿日: 2008/10/05(Sun) 22:03
投稿者花ちゃん
> 計算式は2項の差であり、ご指摘いただいた括弧で括って1項にすることはできません。

失礼しました。

下記なら VB6.0 でも 結果が  8.18545231595635E-12 となり .NET と同じ結果になります
どうも VB6.0 の方がおかしいようですね。

Private Sub Command1_Click()
   Dim sj1 As Double, sj2 As Double, sj3 As Double
   Dim x As Double
   Dim n As Integer, i As Integer
   Dim sj(500) As Double
   n = 14
   sj3 = 0#
   sj2 = 0.00001
   x = 2.40482555769577
   For i = 1 To n - 1
      Dim tmp As Double
      tmp = 2# * (n - i) * sj2
      sj1 = tmp / x
      sj1 = sj1 - sj3
      sj3 = sj2
      sj2 = sj1
   Next i
   Debug.Print (CStr(sj1))
End Sub

Debug.Print CStr(sj1)   '結果  8.18545231595635E-12

[ツリー表示へ]
タイトルRe: 当方疑問解決です。VB6.0の方が正しく計算できていない(再投稿)
記事No8291
投稿日: 2008/10/06(Mon) 19:00
投稿者chime
花ちゃんさん

> 下記なら VB6.0 でも 結果が  8.18545231595635E-12 となり .NET と同じ結果になります
> どうも VB6.0 の方がおかしいようですね。
> Debug.Print CStr(sj1)   '結果  8.18545231595635E-12

上記結果を確認しました。

i=13での結果で
2737.46092971297-2737.46092971296
を計算しているのですが、Yuoさんご指摘の倍精度有効桁数15桁の最後の桁が違います。
直接計算では     8.32489632784927E-12
ご指摘の分割計算では 8.18545231595635E-12 でVB2005と一致します。

しかし、sj=1E-10から計算するとやはり有効桁数最後での違いで
VB6は
非分割計算では      8.15015101848088E-17
分割計算では       7.97972798949331E-17
VB2005は
非分割計算では      8.32667268468867E-17
分割計算では       8.32667268468867E-17
です。
VB6は分割してもVB2005の結果とは一致しません。

VB6、VB2005の結果もいずれも倍精度有効桁数の範囲で8E-12、8E-17
となり、第16桁目以降は議論できないとの結論です。

有益なコメント大変ありがとうございました。 

[ツリー表示へ]
タイトルRe: VB2005の倍精度計算精度は?
記事No8280
投稿日: 2008/10/05(Sun) 20:35
投稿者オショウ
>             sj1 = 2.0# * (n - i) * sj2 / x - sj3

  この式の評価の順序がVB6と.NETで違うのではないでしょうか?

  因みに、倍精度変数と整数の変数が混ざっています。
  整数変数部を倍精度に精度合わせすれば解消しません?

  私も浮動小数点演算で、難儀しましたので・・・

※ 未検証ですので、コーディングして確認して下さい。

以上。

[ツリー表示へ]
タイトルRe^2: VB2005の倍精度計算精度は?
記事No8283
投稿日: 2008/10/05(Sun) 21:28
投稿者chime
>   因みに、倍精度変数と整数の変数が混ざっています。
>   整数変数部を倍精度に精度合わせすれば解消しません?

コメントありがとうございます。

(n-i)をcDbl(n-i)にして倍精度に直しましたが、双方の答えは同じでした。
また 型宣言で as Integer を as Double に変更しても双方同じです。

VB6とVB2005では 大変小さい値の計算精度に差があるのではとの疑問が増大しました。

chime

[ツリー表示へ]
タイトルRe^2: VB2005の倍精度計算精度は?
記事No8284
投稿日: 2008/10/05(Sun) 21:36
投稿者chime
> >             sj1 = 2.0# * (n - i) * sj2 / x - sj3
>
>   この式の評価の順序がVB6と.NETで違うのではないでしょうか?

Reの追加です。

For next 文で
n=13 までのsj1はvb6とvb2005は一致します。
最後のn=14でsj1が大変小さい値になり、一致しなくなります。

従ってn=13までの双方では式の評価は同じであると思いますが。

chime

[ツリー表示へ]
タイトルRe: VB2005の倍精度計算精度は?
記事No8286
投稿日: 2008/10/05(Sun) 22:27
投稿者オショウ
エクセルにて、計算式の簡易な検証を行なってみました。
結果は、.NET方と大差ない結果だったので、もしかして、
VB6の方がおかしいかも・・・

で、気がついたこと・・・
i が、12から13になる部分で、精度的にアンダフロー起こ
してしまっているような・・・
倍精度での最小ケタ付近で、i=6あたりからゼロとなり、
少しづつ大きい値になり、最小ケタ付近がゼロかしていき
ます。
そして、i が、12から13になった部分で、一気に4ケタほ
ど吹っ飛んでいるような・・・

式から考えますと、整数部と小数部を分けた固定小数点演
算方式に変更するか・・・各々を整数演算させる方法に変
更しては?分けるとケタ的に楽になりますから・・・

※ 大昔にやったので、現時点でどうするか・・・忘れました。
  調べてみて下さい。

以上。参考までに

[ツリー表示へ]
タイトルRe^2: VB2005の倍精度計算精度は?
記事No8292
投稿日: 2008/10/06(Mon) 19:07
投稿者chime
オショウさん
> エクセルにて、計算式の簡易な検証を行なってみました。

EXCELで追試計算頂きありがとうございます。
繰り返し計算の途中経過を見ました。
最後のところで、有効桁数ぎりぎりの引き算になっていました。

当方が花ちゃん、オショウ、YuOさんからのコメントを参考に検討し
そのレポートを花ちゃんの下にResしましたのでご覧下さい。

これで解決です。
ご支援ありがとうございました。

chime

[ツリー表示へ]
タイトルRe: VB2005の倍精度計算精度は?
記事No8287
投稿日: 2008/10/05(Sun) 22:44
投稿者YuO
> で答えは8.18545231595635E-12
> と計算結果が異なります。

単純に丸め誤差,ということはありませんか?
VB 2008で実験したところ, i = 13において,
2.737460929712971e+003 - 2.737460929712963e+003
という計算がなされています (e15で書式化)。
doubleの10進表記における有効桁数がそもそも15桁ですから,この計算において
0.000000000000008e+003
と,有効桁数が1桁になっています。
# 繰り返した結果の値ですから,現実的には有効桁数0桁と言ってしまえるかもしれません。

VB6の計算結果は8E-12, VB2005の計算結果も8E-12ですから,ちゃんと計算結果は合致しています。

[ツリー表示へ]
タイトルRe^2: ご指摘の如くです。VB2005の倍精度計算精度は?
記事No8293
投稿日: 2008/10/06(Mon) 19:14
投稿者chime
YuOさん

的確なご返事ありがとうございます。

> 単純に丸め誤差,ということはありませんか?

> # 繰り返した結果の値ですから,現実的には有効桁数0桁と言ってしまえるかもしれません。
当方も結果を再検討しました。ご指摘の如き結論です。
検討結果を花ちゃんさんの下にResしました。

> VB6の計算結果は8E-12, VB2005の計算結果も8E-12ですから,ちゃんと計算結果は合致していま
VB6では非分割計算と分割計算に差があるものの結果は8E-12と同じといえます。

VB2008での検討に感謝いたします。

chime

[ツリー表示へ]