不具合の報告

 投稿者:山中和義  投稿日:2014年 9月10日(水)11時36分0秒
  行列式を計算するプログラムを各モードで実行した場合、結果が異なります。

行列式
| a  b  c | = 1
| d  e  f |
| g  h  i |

| a^2  b^2  c^2 | = 1
| d^2  e^2  f^2 |
| g^2  h^2  i^2 |

を満たすものを探す。


!!OPTION ARITHMETIC RATIONAL
DIM M(3,3)
DIM X(3,3)
FOR A=2 TO 9
   LET M(1,1)=A
   LET X(1,1)=A*A
   FOR B=A TO 9
      LET M(1,2)=B
      LET X(1,2)=B*B
      FOR C=B TO 9
         LET M(1,3)=C
         LET X(1,3)=C*C
         FOR D=2 TO 9
            LET M(2,1)=D
            LET X(2,1)=D*D
            FOR E=2 TO 9
               LET M(2,2)=E
               LET X(2,2)=E*E
               FOR F=2 TO 9
                  LET M(2,3)=F
                  LET X(2,3)=F*F
                  FOR G=2 TO 9
                     LET M(3,1)=G
                     LET X(3,1)=G*G
                     FOR H=2 TO 9
                        LET M(3,2)=H
                        LET X(3,2)=H*H
                        FOR I=2 TO 9
                           LET M(3,3)=I
                           LET X(3,3)=I*I

                           IF DET(M)=1 THEN
                              PRINT DET(X) !debug
                              IF DET(X)=1 THEN
                                 MAT PRINT M;
                                 STOP
                              END IF
                           END IF

                        NEXT I
                     NEXT H
                  NEXT G
               NEXT F
            NEXT E
         NEXT D
      NEXT C
   NEXT B
NEXT A
END



10進、1000桁モード

 :
 :
-1975
387
1327
2267
-1505
1
2  2  3
9  7  6
4  3  2


2進、複素数、有理数モード

 :
 :
217
237
-51
769
1
2  2  3
3  4  2
7  9  6


10進、1000桁モードでは、2進、複素数、有理数モードで求まる値が抜けるようです。



DATA 2,2,3
DATA 3,4,2
DATA 7,9,6
DIM M(3,3),X(3,3)
FOR i=1 TO 3
   FOR J=1 TO 3
      READ T
      LET M(i,J)=T
      LET X(i,J)=T*T
   NEXT J
NEXT i
IF DET(M)=1 THEN MAT PRINT M;
IF DET(X)=1 THEN MAT PRINT X; !bug bug bug  10進、1000桁モード
IF DET3(M)=1 THEN MAT PRINT M;
IF DET3(X)=1 THEN MAT PRINT X;
END
EXTERNAL FUNCTION DET3(M(,)) !3行3列の行列式の値
LET DET3=M(1,1)*M(2,2)*M(3,3)+M(1,2)*M(2,3)*M(3,1)+M(1,3)*M(2,1)*M(3,2) &
&       -M(1,3)*M(2,2)*M(3,1)-M(1,1)*M(2,3)*M(3,2)-M(1,2)*M(2,1)*M(3,3)
END FUNCTION

 

Re: 不具合の報告

 投稿者:白石 和夫  投稿日:2014年 9月10日(水)13時09分59秒
  > No.3486[元記事へ]

オプション―数値メニューで「表示桁数を多く」に
チェックを付けて実行してみるとわかりますが,
DET関数にわずかな誤差があります。
今回は2進モードで正しい値が求まり
10進モードに誤差がある結果となっていますが,
使用しているアルゴリズムは同じなので,
どちらも同じように誤差を含む可能性があります。
行列に関する演算は,計算結果の正確さを保証するのが難しいので,
理論的な計算が必要な場合は有理数モードで実行してください。
 

Re: 不具合の報告

 投稿者:山中和義  投稿日:2014年 9月10日(水)22時35分8秒
  > No.3487[元記事へ]

白石 和夫さんへのお返事です。

> 理論的な計算が必要な場合は有理数モードで実行してください。

次のプログラムのように展開式を使った関数を用いると、どのモードも結果は一致します。
定義した関数DET3は、32ビット整数の範囲で、計算結果は整数として保証されるのでしょうか。
偶々、浮動小数点による近似値が、整数(真の値)と一致したと考えるのでしょうか。


DATA 2,2,3
DATA 3,4,2
DATA 7,9,6
DIM M(3,3),X(3,3)
FOR i=1 TO 3
   FOR J=1 TO 3
      READ T
      LET M(i,J)=T
      LET X(i,J)=T*T
   NEXT J
NEXT i
IF DET(M)=1 THEN MAT PRINT M;
IF DET(X)=1 THEN MAT PRINT X; !10進、1000桁モード
IF DET3(M)=1 THEN MAT PRINT M;
IF DET3(X)=1 THEN MAT PRINT X;
END
EXTERNAL FUNCTION DET3(M(,)) !3行3列の行列式の値
LET DET3=M(1,1)*M(2,2)*M(3,3)+M(1,2)*M(2,3)*M(3,1)+M(1,3)*M(2,1)*M(3,2) &
&       -M(1,3)*M(2,2)*M(3,1)-M(1,1)*M(2,3)*M(3,2)-M(1,2)*M(2,1)*M(3,3)
END FUNCTION

 

Re: 不具合の報告

 投稿者:GAI  投稿日:2014年 9月11日(木)07時10分11秒
  > No.3488[元記事へ]

山中和義さんへのお返事です。

> 次のプログラムのように展開式を使った関数を用いると、どのモードも結果は一致します。
> 定義した関数DET3は、32ビット整数の範囲で、計算結果は整数として保証されるのでしょうか。
> 偶々、浮動小数点による近似値が、整数(真の値)と一致したと考えるのでしょうか。
>
>
> DATA 2,2,3
> DATA 3,4,2
> DATA 7,9,6
> DIM M(3,3),X(3,3)
> FOR i=1 TO 3
>    FOR J=1 TO 3
>       READ T
>       LET M(i,J)=T
>       LET X(i,J)=T*T
>    NEXT J
> NEXT i
> IF DET(M)=1 THEN MAT PRINT M;
> IF DET(X)=1 THEN MAT PRINT X; !10進、1000桁モード
> IF DET3(M)=1 THEN MAT PRINT M;
> IF DET3(X)=1 THEN MAT PRINT X;
> END
> EXTERNAL FUNCTION DET3(M(,)) !3行3列の行列式の値
> LET DET3=M(1,1)*M(2,2)*M(3,3)+M(1,2)*M(2,3)*M(3,1)+M(1,3)*M(2,1)*M(3,2) &
> &       -M(1,3)*M(2,2)*M(3,1)-M(1,1)*M(2,3)*M(3,2)-M(1,2)*M(2,1)*M(3,3)
> END FUNCTION
>

>

上記のプログラムはその前のLET DET3 とどう違うんでしょうか?
これで定義していたらやはり10進、1000桁モード
で結果(MAT PRINT Xを拾わない。)がちがうような気がします。

PARI/GP
という計算ソフトを用いて

| a  b  c |
| d  e  f | ==>a,b,c;d,e,f;g,h,i
| g  h  i |

を探したら、結構沢山現れてびっくりしました。

2,2,3;3,4,2;7,9,6
2,2,3;9,7,6;4,3,2
2,3,3;3,2,5;5,9,7
2,3,3;5,7,9;3,5,2
2,3,4;6,7,9;3,2,2
2,3,5;3,2,3;9,5,7
2,3,5;3,2,9;3,5,7
2,3,6;4,2,9;3,2,7
2,3,7;2,4,9;3,2,6
2,3,9;3,2,5;5,3,7
2,4,9;3,2,6;2,3,7
3,3,5;4,3,4;4,5,9
3,3,5;5,4,9;3,4,4
3,4,4;3,3,5;5,4,9
3,4,4;5,9,4;3,5,3
3,5,7;2,3,5;3,2,9
4,5,9;3,3,5;4,3,4
5,7,9;3,5,2;2,3,3
6,7,9;3,2,2;2,3,4
 

Re: 不具合の報告

 投稿者:白石和夫  投稿日:2014年 9月11日(木)09時25分2秒
  > No.3488[元記事へ]

十進BASICの古いバージョンのDET関数は計算結果の正確さを重視して小行列式を計算する再帰アルゴリズムを用いていたのですが,次数が高くなると格段に遅くなるので,現バージョンは掃出し法で計算しています。
計算の途中に除算を含むので誤差が出やすくなっています。
2次,3次,限定であれば,利用者定義関数を用いて途中計算の精度を保証していくのが確実です。

行列演算は,JIS規格の5.6.4(3)の意味での正確さを保証するのは困難です。
JISの正確さの規定は,表5.1にある「数値関数」に対してのみ適用されるものと解釈しています。
たとえば,

10 DATA  1E18, 123456789, -1E18
20 DATA 1,1,1
30 DIM a(3),b(3)
40 MAT READ a,b
50 PRINT DOT(a,b)
60 END

のようなプログラムに対して正確さを保証するのはかなり面倒です。







 

戻る