[HOME]  [現在掲示板へもどる]     [全部表示 会議室風]  [最新100]  [最新50]   [新着40]    [全部表示 保存用]
番号順 最新50記事     FGALVZ  

11176/11135 BQO00549  konno            Re^10: N88-BASICで素数を表示カウントする PRIME88.BAS
( 1) 24/03/27 00:26 11173:konnoさんへのコメント コメント数:2
> ここ、多くの処理系では割り算よりも掛け算のほうが速いと聞いたことがあるので、
> 割り算を2回するのではなく掛け算と割り算の組み合わせに変更してみました。
> これでどのくらい早くなるかは測定していないからわからない。
> 処理系によっては、むしろ遅くなったりして。

なるほど、そういうやり方もあるのですね。
このプログラムで 10000 指定の実行結果は

Number.10000	  0: 0:30   Prime Number = 1233 

このソースを私の FOR 文のに置き換えてみた結果は

Number.10000	  0: 0: 8   Prime Number = 1233 

実行時間が短縮されました。
コンパイラでは最適化でインタプリタと違う結果になるようです。
どこがどう効いたかわからないので、変更ソースを上げます。

1320 *START
1330 TM$=TIME$
1340 I=2:GOSUB *PRINT1
1350 FOR I=3 TO N                                        '★
1360  ' IF INT(I/2)*2 = I THEN *EXIT2                    '☆
1362   i2=i/2:i3=int(i/2):IF i2=i3 THEN goto *EXIT2      ' 合成数
1370 '    J=3                                            '☆
1380 '    WHILE (J<SQR(I)) AND (INT(I/J)*J<>I)           '☆
1382      FOR J=3 TO int(SQR(I)) STEP 2                  '★ 偶数をスキップ
1390 '      J=J+1                                        '☆
1392        I2=I/J:I3=INT(I/J):IF I2=I3 THEN GOTO *EXIT1 '★ 合成数
1400 '      WEND                                         '☆
1402      NEXT J                                         '★
1404      *EXIT1                                         '★
1406 '     if i=169 then print "   13 =";i;sqr(i);j:goto *exit2
1408 '     IF i=169 then if J=SQR(I) THEN *EXIT2
1410      IF SQR(I)<J THEN GOSUB *PRINT1
1420   *EXIT2
1430 NEXT I
1440 I=I-1

ちなみに、VGA版の結果は

Number.10000	  0: 0' 1   Prime Number = 1229 

結果の素数の数が 4 違いますね。

---  N88  --- 
 169 	13*13
 5041 	71*71
 6241 	79*79
 9409 	97*97

10000 で 4 箇所 合成数が含まれています。
何が原因かわからないです。


11177/11135 BQO00549  konno            Re: PRIME88.BAS で 「169=素数?」問題解決か
( 1) 24/03/27 22:56 11175:konnoさんへのコメント
不具合の原因がわかりました。
SQR() 関数の結果判定に問題が有ったようです。

PRIME98.BAS

1320 *START
1330 TM$=TIME$
1340 I=2:GOSUB *PRINT1
1350 FOR I=3 TO N                                   '
1360   i2=i/2:i3=int(i/2):IF i2=i3 THEN *EXIT2      ' 合成数
1370      j2=int(SQR(I))                            '
1380      FOR J=3 TO j2 STEP 2                      ' 偶数をスキップ
1390        I2=I/J:I3=INT(I/J):IF I2=I3 THEN *EXIT2 ' 合成数
1400      NEXT J                            
1410    IF J>SQR(I)+.0001 THEN GOSUB *PRINT1        '★
1420 *EXIT2
1430 NEXT I
1440 I=I-1

このように、SQR() に +0.0001 を足したら問題が解消されました。
計算精度の問題か、最小桁が切り捨てられているのでしょうか。
いくつ足せばいいのか桁を変えて試してみました。

1410    IF J>SQR(I)+.000001 THEN GOSUB *PRINT1		ng
Number.10000	  0: 0:29   Prime Number = 1233 
169  5041  6241  9409 	ng

1410    IF J>SQR(I)+.00001 THEN GOSUB *PRINT1		ng
Number.10000	  0: 0:30   Prime Number = 1232 
5041  6241  9409 	ng

1410    IF J>SQR(I)+.0001 THEN GOSUB *PRINT1		ok
Number.100000	  0: 2:29   Prime Number = 9592 

どうも N88BASIC の問題のような気がしますが、実機でどうなるか知りたいですね。


11178/11135 CXB00940  としき           Re^11: N88-BASICで素数を表示カウントする PRIME88.BAS
( 1) 24/03/28 00:43 11176:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
あ、これはまずい。

> このプログラムで 10000 指定の実行結果は
> Number.10000	  0: 0:30   Prime Number = 1233 
> このソースを私の FOR 文のに置き換えてみた結果は
> Number.10000	  0: 0: 8   Prime Number = 1233 
> 実行時間が短縮されました。

この差は大きすぎる。プログラムに間違いがあるから。

> 1382      FOR J=3 TO int(SQR(I)) STEP 2                  '★ 偶数をスキップ
> 1390 '      J=J+1                                        '☆

ここのところ、STEP 2 なんだから、J=J+2 でなければならない。
単純にループ回数が2倍になってしまう。
ということで、おそらく、30秒は15秒ぐらいまで短縮できるはずだけど、それでも
やっぱり8秒までは縮まらないと思う。

SQR関数の精度のほうは、どうしようかな。


11179/11135 BQO00549  konno            SQRの計算式
( 1) 24/03/30 15:58 11178:としきさんへのコメント コメント数:1
SQRの計算を自前で出来ないか検索してみました。
「本の虫」のサイトの「平方根のアルゴリズム 」
https://cpplover.blogspot.com/2010/11/blog-post_20.html

ここがわかりやすかったのでここから引用します。
-----------------------------------------------------------

ここで使うのは、バビロニア人の方法(Babylonian method)と呼ばれている、歴史あるアルゴリズムである。
この方法は、手動でも、プログラミングでも、非常に簡単に計算できる、大変便利で汎用的なアルゴリズムである。
しかも、速度もそれほど遅くない。 

double sqrt( double s )
{
    double x = s / 2.0 ; // Is there any better way to determine initial value?
    double last_x = 0.0 ; // the value one before the last step

    while ( x != last_x ) // until the difference is not significant
    { // apply Babylonian method step
        last_x = x ;
        x = (x + s / x) / 2.0 ;
    }
    
    return x ;
}

-----------------------------------------------------------

これを TurboBasic に置き換えたテストが

3000 ' SQR1.BAS
3010 'defdbl a-z
3020 screen 0
3030 cls
3040 input s
3050 x = s / 2.0  '; // Is there any better way to determine initial value?
3060 lastx = 0.0 '; // the value one before the last step
3070 '    while ( x != lastx ) '// until the difference is not significant
3080 'loop1:
3090        lastx = x 
3100        x = (x + s / x) / 2.0 
3110   if   x <> lastx  then 3080 'loop1
3120   print "SQR(";s;")=";x,lastx
3130   input a
3140 end

3020行をコメントにすれば N88BASIC でも動作します。
これをサブルーチンにして PRIME88.BAS に貼り付けて

1320 *START
1330 TM$=TIME$
1340 I=2:GOSUB *PRINT1
1350 FOR I=3 TO N
1360     IF INT(I/2)*2 = I THEN *EXIT2
1370         J=3
1375         s=I:gosub 3050:s=xx                '★
1380         WHILE (J<s) AND (INT(I/J)*J<>I)    '★
1390             J=J+1                          '★★
1400         WEND
1410         IF J>s THEN GOSUB *PRINT1          '★
1420     *EXIT2
1430 NEXT I
1440 I=I-1

この結果は
Number.10000	  0: 0:14   Prime Number = 1229 

おお、素数が合ってるし、時間が半分になりました。
SQR()関数を2回実行していたのをサブルーチン1回にしたのが効いたみたいです。

さらに、★★ のところを
1390             J=J+2                          '★★
このように +2 に変更した結果
Number.10000	  0: 0: 9   Prime Number = 1229 

おお、時間がさらに短縮して、FOR文のループとほぼ同じになりました。
ちなみに FOR文のソースにこのサブルーチンを組み込んだら
Number.10000	  0: 0:11   Prime Number = 1229 

2〜3秒遅くなりましたね。これが関数とサブルーチンの速度差と思われます。
思ったよりも差が無いなぁ、というのが感想です。(^^;

素数のネタはこの辺でしまいにしたいところですね。


11180/11135 CXB00940  としき           Re: SQRの計算式
( 1) 24/03/30 23:41 11179:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
> これを TurboBasic に置き換えたテストが

えと、whileのループをifのジャンプに変更したのはなぜでしょうか。
こちらのほうが速いのですか?

> 素数のネタはこの辺でしまいにしたいところですね。

そうですね。
明日、31日に実家へ行くので、時間が取れたら実機でいくつか試したいところ。
実は、父の命日が31日なんですよ。
ただ、日が近いということで、多くの場合、墓参りはお彼岸に集約されています。
天候だとか諸事情でお彼岸に墓参りできないときだけ命日に墓参り、と言う感じ
なのですが、まぁいろいろと存在しない事情をでっち上げて実家に顔を出すところ
まではアポイント済み。ただ、時間が取れるかどうかは別問題なんで。


11181/11135 CXB00940  としき           Re^10: N88-BASICで素数を表示カウントする PRIME88.BAS
( 1) 24/03/31 14:09 11173:konnoさんへのコメント
参照先:http://toshiki.la.coocan.jp/
実家に来ています。
まず、先日アップしたあのプログラムをそのまま実行したのですが

> Number.1000	  0: 0' 0   Prime Number = 168 

うちのN88-BASICでは、素数の数が168になりました。
169は素数としてカウントされませんでした。
どうやらSQR関数、うちの環境のほうが精度が高いらしい。
ちなみに、ファイル出力ではなく画面表示で、所要時間は0秒〜1秒くらい。
あまり違いはないですね。

とりあえず時間切れ、続きは後ほど。

11182/11135 CXB00940  としき           Re^11: N88-BASICで素数を表示カウントする PRIME88.BAS
( 1) 24/03/31 15:48 11176:konnoさんへのコメント
参照先:http://toshiki.la.coocan.jp/
続いて、先日上げたプログラムのまま、すなわち、SQR関数の部分もいじらず、
変数Jのカウントアップも1ずつのままで10000までの結果。

> Number.10000	  0: 0' 1   Prime Number = 1229 

素数の数は1229と出ました。やっぱりうちの環境では誤差がないみたい。
ちなみに、所要時間は、画面表示だと12秒、ファイル出力だと13秒。
これはいささか直感と記憶に反している。
記憶だと、画面表示のほうがスクロールアップに時間がとられるので遅くなったはず
なのですがね。ま、でも、誤差の範囲。

次、変数 J のカウントアップを J=J+2 としたら所要時間は7秒まで短縮。
やっぱりループ回数が2倍というのは大きかった模様。
素数の数は1229なので、計算誤差の問題もないですね。

ところで、うちのBASICインタープリタは1987年製のVer5.0というやつです。
konnoさんのところの版数とかはわかりますか?


11183/11135 CXB00940  としき           Re^9: N88-BASICで素数を表示カウントする PRIME88.BAS
( 1) 24/03/31 16:08 11172:としきさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
実家での検証、最後。

> ここ、多くの処理系では割り算よりも掛け算のほうが速いと聞いたことがあるので、
> 割り算を2回するのではなく掛け算と割り算の組み合わせに変更してみました。
> これでどのくらい早くなるかは測定していないからわからない。

メインのループを

1350 FOR I=3 TO N
1360     IF INT(I/2)*2 = I THEN *EXIT2
1370         J=3:I2=I/J:I3=INT(I/J)
1380         WHILE J<SQR(I) AND I2<>I3
1390             J=J+2:I2=I/J:I3=INT(I/J)
1400         WEND
1410         IF J>SQR(I) THEN GOSUB *PRINT1
1420     *EXIT2
1430 NEXT I

こうやって、割り算2回で20000までの素数を求めたら21秒で2262個。
元のままの、割り算と掛け算だと17秒、2262個。
うん、やっぱりうちでは、誤差というには差が大きいくらい、掛け算のほうが早い
模様。


以上、レス元が分散して申し訳ありませんが、実家での検証3連発でした。


11184/11135 BQO00549  konno            Re^2: SQRの計算式
( 1) 24/03/31 22:26 11180:としきさんへのコメント
> えと、whileのループをifのジャンプに変更したのはなぜでしょうか。
> こちらのほうが速いのですか?

私は while文をあまり使わないので、無意識に 慣れた IF文に変えてしまってました。(^^;
オリジナルのソースに wend を入れるだけでしたね。(^^;

#11179 で書きましたが
> ちなみに FOR文のソースにこのサブルーチンを組み込んだら
> Number.10000	  0: 0:11   Prime Number = 1229 
> 2〜3秒遅くなりましたね。これが関数とサブルーチンの速度差と思われます。

同じ条件では、while文の方が速いと思われます。
そこで、このサブルーチンの while と FOR で比較してみました。

FOR文     Number.100000   0: 2:51   Prime Number = 9592 
WHILE文   Number.100000   0: 2:47   Prime Number = 9592 

10万で4秒の差でした。思ったよりも差が小さかったですね。
SQR 1回あたり7〜10回程度のループで済んでいるから差が小さいのでしょう。

> なのですが、まぁいろいろと存在しない事情をでっち上げて実家に顔を出すところ
> まではアポイント済み。ただ、時間が取れるかどうかは別問題なんで。

お手間を取らせて申し訳ないですが、よろしくお願いします。


11185/11135 BQO00549  konno            Re^10: N88-BASICで素数を表示カウントする PRIME88.BAS
( 1) 24/04/01 00:27 11183:としきさんへのコメント コメント数:2
ここにまとレスします。

> > Number.1000	  0: 0' 0   Prime Number = 168 
> うちのN88-BASICでは、素数の数が168になりました。
> 169は素数としてカウントされませんでした。
> どうやらSQR関数、うちの環境のほうが精度が高いらしい。

これは驚きです! ということは、98エミュの問題か、ファイルが壊れているかですね。

> ちなみに、所要時間は、画面表示だと12秒、ファイル出力だと13秒。
> これはいささか直感と記憶に反している。

TurboBasic でも同じような結果です。画面表示は遅いというのは思い込みなのでしょう。

> ところで、うちのBASICインタープリタは1987年製のVer5.0というやつです。
> konnoさんのところの版数とかはわかりますか?

88-BASIC(86) Compiler version 6.0 
1988/08/24  00:00            61,440 BASICC.COM

うちで使用したコンパイラ版はこれですね。

> こうやって、割り算2回で20000までの素数を求めたら21秒で2262個。
> 元のままの、割り算と掛け算だと17秒、2262個。
> うん、やっぱりうちでは、誤差というには差が大きいくらい、掛け算のほうが早い
> 模様。

なるほど。やはり掛け算が速いのですね。

> 以上、レス元が分散して申し訳ありませんが、実家での検証3連発でした。

お忙しい中色々検証していただき、ありがたいです。
N88BASICの精度疑惑も晴れたので、98エミュの検証が必要そうですね。


11186/11135 BQO00549  konno            T98-NEXT でN88BASIC検証
( 1) 24/04/02 00:16 11185:konnoさんへのコメント
以前N88BASICが動かなかったT98-NEXT で再挑戦しました。
コンパイラ版が動かなかったのはメモリ不足だったようです。
ATOK8がメインメモリに居座っていたので削除したら動きました。(^^;
ただし、BATのオプションが効かなくて、ソースファイル名を手打ちしました。(^^;
結果はほかのエミュと同じで駄目でした。

インタプリタも、実機ROMにチェックを入れたら動きました。
結果はやっぱり駄目でした。
98エミュは全滅です。

うーむ、このバージョンの N88BASIC に問題がある可能性があるのでしょうか。


11187/11135 CXB00940  としき           Re^11: N88-BASICで素数を表示カウントする PRIME88.BAS
( 1) 24/04/03 16:20 11185:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
> これは驚きです! ということは、98エミュの問題か、ファイルが壊れているか

エミュの問題、というのは考え易いところです。
が、ファイルの破壊となった場合、そんな精度に関係するところが絶妙に壊れる、
というのはなかなか考えにくい。
ただ、N88(86)では使っていない技術だとは思いますが、いくつかの処理系では、
関数の速度と精度向上のため、全てを計算で求めるのではなく、大きな定数表を
使う場合がある、と聞いたことはあります。とはいっても超巨大というほどの表
ではなく、引数のいくつかに分解して、それぞれの結果を足すとかかけるとかで
速度と精度を両立させます。
その場合は、その定数表の一部だけが間違っているとか精度が足りないことが発生
しうるわけです。でも、これって、三角関数とか対数関係の関数で使うワザだった
ような気がする。
平方根でも使うことがあるのかなぁ。

> 88-BASIC(86) Compiler version 6.0 
> 1988/08/24  00:00            61,440 BASICC.COM

これ、頭のNが欠けているのは転記ミスですよね。
実は、私の記憶でも、88年のVer6が最終版、ということになっているからです。
そして私の手元には87年のVer5しかないわけですが、バージョンアップするかどうか
という判断に際して、どこが変わったかという情報がなくてバージョンアップを
しなかった、というおぼろげな記憶があります。
ところでkonnoさんのところでは、TurboBasicではなく、N88BASICのコンパイラと
インタプリタで同じ結果になります?
あと、インタプリタとコンパイラでバージョンは同じですか?


11188/11188 CXB00940  としき           「全部表示 会議室風」が何かおかしい
( 1) 24/04/03 17:29 コメント数:1
参照先:http://toshiki.la.coocan.jp/
こちらの掲示板での過去ログ表示で気がつきました。
[全部表示 会議室風]のリンクを押して表示される発言の中に、そのログのトップの
ツリーのルートの発言が含まれていないようです。
具体的には

過去ログ26では#10734
過去ログ25では#10632
過去ログ24では#10229
・・・
過去ログ2では#974
過去ログ1では#418

が表示されないようです。
ご確認をお願いします。


11189/11135 BQO00549  konno            Re^12: N88-BASICで素数を表示カウントする PRIME88.BAS
( 1) 24/04/04 01:01 11187:としきさんへのコメント コメント数:1
> その場合は、その定数表の一部だけが間違っているとか精度が足りないことが発生
> しうるわけです。でも、これって、三角関数とか対数関係の関数で使うワザだった
> ような気がする。
> 平方根でも使うことがあるのかなぁ。

原因が分かったような気がします。
N88BASIC(86) では、FOR文が倍精度では動かないので単精度でやって NG だったのですが
1030 defdbl A-Z と変数を倍精度にし、FOR文の I だけ I! で単精度でやってみました。

1340 I=2:GOSUB *PRINT1
1342 i=3
1350 FOR I!=3 TO N
1360     IF INT(I/2)*2 = I THEN *EXIT2
1370         J=3
1380         WHILE (J<SQR(I)) AND (INT(I/J)*J<>I)
1390             J=J+1
1400         WEND
1410         IF J>SQR(I) THEN GOSUB *PRINT1
1420     *EXIT2
1422 i=i+1
1430 NEXT I!
1440 I=I-1

他は変えていませんが、このプログラムでは 169 が表示されず、正常になりました。
# 汚れていたのは SQR(I) だったんです。(By now shika)

変数 I が倍精度だと数値の比較が正常なのに、単精度だと 表示は整数でも内部の計算がズレる模様。
想像ですが、例えば比較計算は倍精度で、表示は単精度に丸められているとか。

> > 88-BASIC(86) Compiler version 6.0 
> > 1988/08/24  00:00            61,440 BASICC.COM
> これ、頭のNが欠けているのは転記ミスですよね。

はい、そうです。失礼しました。m(__)m

> ところでkonnoさんのところでは、TurboBasicではなく、N88BASICのコンパイラと
> インタプリタで同じ結果になります?

同じ結果になります。上の実験はインタプリタではしてないですが。

> あと、インタプリタとコンパイラでバージョンは同じですか?

同じだと思います。起動メッセージが同じなので。
日付は少し違いますね。


11190/11188 BQO00549  konno            Re: 「全部表示 会議室風」が何かおかしい
( 1) 24/04/04 01:07 11188:としきさんへのコメント コメント数:1
> こちらの掲示板での過去ログ表示で気がつきました。
> [全部表示 会議室風]のリンクを押して表示される発言の中に、そのログのトップの
> ツリーのルートの発言が含まれていないようです。

げげげ、・・・・・・

確認しました。しばしお待ちください。m(__)m


11191/11135 CXB00940  としき           Re^13: N88-BASICで素数を表示カウントする PRIME88.BAS
( 1) 24/04/04 12:15 11189:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
「妙だな」というのは、どこぞの小学生のよく言うせりふですが、それはさておき。
#11164にも書きましたが、N88だと単精度でも倍精度でも上限は同じです。
また、演算速度が単精度の方が速いという理由から私は全て単精度でやっているの
ですが、konnoさんが倍精度を選ばれている理由は何ですか?
他のBASICだと上限が違うとかあるのでしょうか。

さて、私のコードでは全て単精度でやっています。なので、精度変換の問題は出ない
はず。実際、うちでは問題が出ていません。
でも、#11173では、同じコードで問題が出ているということです。
なので、これは精度変換の問題ではないと思われます。


> 他は変えていませんが、このプログラムでは 169 が表示されず、正常になりました。

このプログラムだと、単精度の I! と倍精度の I の両方でカウント処理が発生します。
倍精度の I だけ使って WHILE のループにしたほうがいいような気がします。


> 想像ですが、例えば比較計算は倍精度で、表示は単精度に丸められているとか。

N88のマニュアルでは、異なる型同士での演算の場合は高い精度のほうに合わせて
行われるとのこと。これは比較演算でも同じはず。

で、私の疑っていた、konnoさんのところのコンパイラとインタプリタのバージョン
違いという疑いは晴れたので、するとあとは、私のところのバージョンとkonnoさん
のところのバージョンが異なる、という問題は残ります。
とりあえず、出発点は#11173。同じコードなのに結果が異なる、ということ。
あ、重要な問題がある。
私がもしかしたら、アップしたのとは異なるコードを実行していた可能性。
実はこの可能性が一番高いかも。


11192/11135 CXB00940  としき           Re: PRIME88.BAS で 「169=素数?」問題
( 1) 24/04/05 02:07 11175:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
自分で実験できないのにあれこれ言って申し訳ありません。

> 条件を色々変えて試しても結果は変わらなかったのですが、ひとつだけ
> N88P.BAS
> ところがオリジナルを若干修正した以下
> PN88.BAS

N88P.BASとPN88.BAS、konnoさん的には「若干修正」かもしれませんが、内部的には
もしかしたら大幅な修正かもしれません。
そこで結果を教えていただきたいのが、

> PN88.BAS
> 110  defdbl a-z                                 '倍精度指定

ここを単精度指定にしたらどうなるか、ということ。
とても興味があります。


11193/11188 BQO00549  konno            Re^2: 「全部表示 会議室風」が何かおかしい
( 1) 24/04/06 00:30 11190:konnoさんへのコメント コメント数:1
> > [全部表示 会議室風]のリンクを押して表示される発言の中に、そのログのトップの
> > ツリーのルートの発言が含まれていないようです。
> 確認しました。しばしお待ちください。m(__)m

ううう、3日間腐海暗闇の中で藻掻いていました。(;_;)

wforum.cgi を色々弄ってみましたがどうやってもルート発言が表示されません。(>_<)
仕方がないので過去ログの先頭に改行を追加してみたら表示されました。
うげぇ、今までの苦労は何だったんだ・・・・

唯の改行だとツリー表示にゴミが表示されるので、現行ログの形式でダミーを入れました。

0001<>00.00.00.00<>1097421569<>
番号 IPアドレス 書き込み時間(古ければスキップ?)

このように、書き込み時間が古ければ自動的にスキップしてくれるようです。
この処理をどこでやっているのかはわかりません。
色々弄った版はツリー表示がおかしくなったので、修正前のに戻したら直りました。

結局 cgi は弄らずに、過去ログ形式を変更することで解決しました。(-_-;) ヤレヤレダゼ
何かおかしなところに気が付いたら教えてください。m(__)m


11194/11135 BQO00549  konno            Re^14: N88-BASICで素数表示の問題
( 1) 24/04/06 01:40 11191:としきさんへのコメント コメント数:1
> #11164にも書きましたが、N88だと単精度でも倍精度でも上限は同じです。
> また、演算速度が単精度の方が速いという理由から私は全て単精度でやっているの
> ですが、konnoさんが倍精度を選ばれている理由は何ですか?

N88 は FOR文のカウントに倍精度が使えない制限があるようです。
それで単精度でやったら問題が出たので、倍精度でやり直してみたという経緯です。

> さて、私のコードでは全て単精度でやっています。なので、精度変換の問題は出ない
> はず。実際、うちでは問題が出ていません。
> でも、#11173では、同じコードで問題が出ているということです。
> なので、これは精度変換の問題ではないと思われます。

私は N88BASIC の特定のバージョン(V6.0)の問題なのではないかと疑っています。
もちろん 98エミュの問題の可能性も排除できないので実機で確認したいのです。

> > 他は変えていませんが、このプログラムでは 169 が表示されず、正常になりました。
> このプログラムだと、単精度の I! と倍精度の I の両方でカウント処理が発生します。
> 倍精度の I だけ使って WHILE のループにしたほうがいいような気がします。

私は while の入れ子は特に間違えやすいので、FOR文でやりました。
結果は同じになると思います。

> N88のマニュアルでは、異なる型同士での演算の場合は高い精度のほうに合わせて
> 行われるとのこと。これは比較演算でも同じはず。

なるほど、それで謎の挙動がわかったような気がします。
比較の実験結果をあげてみます。


11195/11135 BQO00549  konno            Re^2: PRIME88.BAS で 「169=素数?」問題
( 1) 24/04/06 02:05 11192:としきさんへのコメント コメント数:2
> > PN88.BAS
> > 110  defdbl a-z                                 '倍精度指定
> 
> ここを単精度指定にしたらどうなるか、ということ。
> とても興味があります。

丁度良いテストプログラムを作ったので上げます。

3000 ' SQR88.BAS
3010 'defdbl a-z
3012 defsng a-z
3020 'screen 0
3030 cls
3040 input s
3042 OPEN "SQR.dat" FOR OUTPUT AS #1
3046 cc=0
3050 x = s / 2.0  '; // Is there any better way to determine initial value?
3060 lastx = 0.0 '; // the value one before the last step
3070 'while ( x != lastx ) '// until the difference is not significant
3090      lastx = x 
3100      x = (x + s / x) / 2.0 
3112      cc=cc+1
3114      print x;lastx,cc
3116      print#1, x;lastx,cc
3110  if   x < lastx  then 3070
3120  print "SQR(";s;")=";x,lastx,cc
3122  print#1, "SQR(";s;")=";x,lastx,cc
3124  close
3130  input a
3140 end

このプログラムで、TurboBasic の結果は

単精度
 43.25              84.5                   1 
 23.57875633239746  43.25                  2 
 15.37311267852783  23.57875633239746      3 
 13.18316555023193  15.37311267852783      4 
 13.00127220153808  13.18316555023193      5 
 13                 13.00127220153808      6 
 13                 13                     7 
SQR( 169 )= 13   13      7 回

倍精度
 43.25              84.5                   1 
 23.57875722543352  43.25                  2 
 15.37311286945074  23.57875722543352      3 
 13.18316604902914  15.37311286945074      4 
 13.00127244856782  13.18316604902914      5 
 13.00000006226796  13.00127244856782      6 
 13                 13.00000006226796      7 
 13                 13                     8 
SQR( 169 )= 13   13       8 回

倍精度の方が収束するのに1回多く掛かっています。
どちらでも計算は倍精度でやっているのがわかります。
一方、N88BASIC の結果は

単精度
 43.25            84.5             1 
 23.5788          43.25            2 
 15.3731          23.5788          3 
 13.1832          15.3731          4 
 13.0013          13.1832          5 
 13               13.0013          6 
 13               13               7 
SQR( 169 )= 13  13    7 回

倍精度
 43.25              84.5                   1 
 23.57875722543353  43.25                  2 
 15.37311286945074  23.57875722543353      3 
 13.18316604902914  15.37311286945074      4 
 13.00127244856782  13.18316604902914      5 
 13.00000006226796  13.00127244856782      6 
 13                 13.00000006226796      7 
 13                 13                     8 
 13                 13                     9 
SQR( 169 )= 13   13      9 回

おや、単精度の場合は SQR の計算も単精度なのか、それとも表示だけなのか?
倍精度では収束したのにさらにもう1回多く計算しています。???
この結果は、WHILE 文にしても同じでした。
そして、単精度の時だけ 169 が素数と誤判定しているのです。

このことから私は、「>」や「>=」などの比較式で単精度の時だけ誤差が出ていると疑ったのです。
V6.0に問題が有るかどうかは、実機で確認する以外にわからないと思います。


11196/11188 CXB00940  としき           Re^3: 「全部表示 会議室風」が何かおかしい
( 1) 24/04/06 10:50 11193:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
> 仕方がないので過去ログの先頭に改行を追加してみたら表示されました。

この現象から見ると、過去ログと現行ログでの分岐に問題がありそうですね。
まさかと思いますが、そもそも分岐していない、とか。

> この処理をどこでやっているのかはわかりません。

もともとこのルーチン、作ったのはkonnoさんですから。
作った本人がわからないようではどうしようもありません。
もう大丈夫だとは思いますが、不要なコメント、とかいう目くらましにやられて
いる、ということはないでしょうか。

とりあえず、今のところは問題ないような感じです。


11197/11135 CXB00940  としき           Re^15: N88-BASICで素数表示の問題
( 1) 24/04/06 11:26 11194:konnoさんへのコメント
参照先:http://toshiki.la.coocan.jp/
> N88 は FOR文のカウントに倍精度が使えない制限があるようです。

そです。
これはマニュアルにも明記されている仕様です。

> それで単精度でやったら問題が出たので、倍精度でやり直してみたという経緯です。

なるほど、いきさつが理解できました。

> 私は N88BASIC の特定のバージョン(V6.0)の問題なのではないかと疑っています。

現時点では、私もこの線が濃厚だと思っております。

> 私は while の入れ子は特に間違えやすいので、FOR文でやりました。

BASICを極めたいのならWHILEは避けて通れません。
私もかなり錆付いてはいますが、まだkonnoさんより私のほうが、BASICに関しては
一日の長がありそうな感じ。

> 結果は同じになると思います。

いや、結果の問題ではなく速度の問題。
加算するのはループカウンタだけでいいでしょう、ということです。


11198/11135 CXB00940  としき           Re^3: PRIME88.BAS で 「169=素数?」問題
( 1) 24/04/06 11:27 11195:konnoさんへのコメント
参照先:http://toshiki.la.coocan.jp/
> 3000 ' SQR88.BAS

これ、あとで私も検証してみます。最短で今日の午後。

> このプログラムで、TurboBasic の結果は

> どちらでも計算は倍精度でやっているのがわかります。

ダウト。

> 単精度
>  43.25              84.5                   1 
>  23.57875633239746  43.25                  2 

> 倍精度
>  43.25              84.5                   1 
>  23.57875722543352  43.25                  2 

もうここですでに値が異なります。
すなわち、表示だけ倍精度、という可能性が濃厚。

> おや、単精度の場合は SQR の計算も単精度なのか、それとも表示だけなのか?

N88の場合、仕様では、引数の型が結果の型、ということになっています。
このプログラムでは、2.0 という単精度型で割り算をしています。
ここを 2# としてみたら、もしかしたら違いが出てくる可能性があります。


11199/11135 CXB00940  としき           Re^3: PRIME88.BAS で 「169=素数?」問題
( 1) 24/04/06 14:51 11195:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
実家に来ています。
うちの母、風邪気味だというのに買い物に行きたいのだとか。
母と同居しているうちの弟、免許すら持っていないので、その手の案件は私が対応。
ということで、まもなく連れ出されてしまいますが、その前に。

まず、うちのN88BASIC、コンパイラはありません。
タイムスタンプは以下。

N88BASIC EXE       161,280 87-10-30    0:00
N88BASIC LIB       178,176 86-08-14   13:51

ん〜、ライブラリのほう、もしかしたらバージョンが古いかも。
そして、この環境で

> 丁度良いテストプログラムを作ったので上げます。
> 3000 ' SQR88.BAS

このプログラムを load して list をみたら、

3050 X = S / 2!  '; // Is there any better way to determine initial value?
3100      X = (X + S / X) / 2! 

と、自動で変換されてしまっていました。
もしかしたらkonnoさんのところでも、この手の意図せざる自動変換が発生している
かもしれません。当然、コンパイラのほうでも。
一度、インタプリタのほうで list をたたいて、自動変換の有無を確認されたほうが
いいでしょう。

そして、読み込ませてすぐに run させたら、あれ?
konnoさんのところと実行結果が異なる。
何が異なるって、途中経過が一切表示されない。妙だな。
よくリストを見たら、結果表示がループの外に出ている。
こういうトリックはやめて欲しいけど、でも私も良くやるので人のことは言えない。
とりあえず、3110行の if 文を3123行に持ってきて、ここで時間切れ。

続きは帰宅後。
何時ぐらいになるかなぁ。


11200/11135 CXB00940  としき           Re^4: PRIME88.BAS で 「169=素数?」問題
( 1) 24/04/06 23:09 11199:としきさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
> 続きは帰宅後。

続きです。

> よくリストを見たら、結果表示がループの外に出ている。
> こういうトリックはやめて欲しいけど、でも私も良くやるので人のことは言えない。

違う。
結果表示が改行されず、同一行に上書きされているような感じ。
つまり、トリックは私が仕掛けた、ということで。
大変失礼しました。
そして、私が悪かったにもかかわらず

> とりあえず、3110行の if 文を3123行に持ってきて、ここで時間切れ。

こんなことをやったから、出力書式がめちゃくちゃ。
とりあえず、konnoさんと同じような書式にVzでそろえた結果です。

単精度2.0
 43.25  84.5   1 
 23.5788  43.25              2 
 15.3731  23.5788            3 
 13.1832  15.3731            4 
 13.0013  13.1832            5 
 13  13.0013   6 
 13  13        7 
SQR( 169 )= 13               13            7 

倍精度2.0
 43.25  84.5   1 
 23.57875722543353  43.25    2 
 15.37311286945074  23.57875722543353      3 
 13.18316604902914  15.37311286945074      4 
 13.00127244856782  13.18316604902914      5 
 13.00000006226796  13.00127244856782      6 
 13  13.00000006226796       7 
 13  13        8 
 13  13        9 
SQR( 169 )= 13               13            9 

念のため、2! のところを全て 2# にしてみたけど、結果は同じでした。

どうも、見たところ、結果は全て同じ。
収束したのに1回多くループを回っているところも同じ。
にもかかわらず、うちの環境では、169は素数にならない。
まだアップしたままのprime88.zipを再度落としてみて、ファイル比較して同じもので
あることも確認済み。そして、名前を変えて、新しく落としたほうを実行してみて
169が素数にならないことも確認済み。

何じゃこりゃ。


11201/11188 BQO00549  konno            Re^4: 「全部表示 会議室風」が何かおかしい
( 1) 24/04/07 00:51 11196:としきさんへのコメント
> > 仕方がないので過去ログの先頭に改行を追加してみたら表示されました。
> 
> この現象から見ると、過去ログと現行ログでの分岐に問題がありそうですね。
> まさかと思いますが、そもそも分岐していない、とか。

うう、そのまさかでした。(>_<)

	open(IN,"$logfile") || &error("Open Error: $logfile");
	$top = <IN>;

こうなっていたところを
#	$top = <IN>;
	$top = <IN> if ($in{'act'} ne "past");

こう変更したら今までの過去ログファイルのままでも正常になりました。
うう、これも試していたのに弄りすぎておかしくなっていたようです。(>_<)
アドバイスありがとうございました。m(__)m


11202/11135 CXB00940  としき           Re^5: PRIME88.BAS で 「169=素数?」問題
( 1) 24/04/07 01:17 11200:としきさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
訂正、ではないような。
補足、かな。

> > よくリストを見たら、結果表示がループの外に出ている。
> > こういうトリックはやめて欲しいけど、でも私も良くやるので人のことは言えない。
> 
> 違う。
> 結果表示が改行されず、同一行に上書きされているような感じ。
> つまり、トリックは私が仕掛けた、ということで。

結果表示が上書きのよう、というのはそのとおりなんですが。
結果表示がループの外、というトリックは、やっぱりkonnoさんだった。

#11195より

> 3070 'while ( x != lastx ) '// until the difference is not significant
> 3090      lastx = x 
> 3100      x = (x + s / x) / 2.0 
> 3112      cc=cc+1
> 3114      print x;lastx,cc
> 3116      print#1, x;lastx,cc
> 3110  if   x < lastx  then 3070
> 3120  print "SQR(";s;")=";x,lastx,cc
> 3122  print#1, "SQR(";s;")=";x,lastx,cc

これ、行番号順に並んでいないじゃないのよさ。
BASICの場合、行番号順に実行されるわけですから、実行時には

> 3070 'while ( x != lastx ) '// until the difference is not significant
> 3090      lastx = x 
> 3100      x = (x + s / x) / 2.0 
> 3110  if   x < lastx  then 3070
> 3112      cc=cc+1
> 3114      print x;lastx,cc
> 3116      print#1, x;lastx,cc
> 3120  print "SQR(";s;")=";x,lastx,cc
> 3122  print#1, "SQR(";s;")=";x,lastx,cc

となるわけでして。
まったくもう。
前にも書いたと思いますが、もうちょっと行番号の並びとかインデントに気を配って
プログラムを書いていただけないでしょうか。
バグが混入し易くなりますよ、と、繰り返しお伝えしていますよね。
こうやって、残り少ない人生を無駄にしてしまうわけですから。

でも、このプログラムだと、N88なら、ループ内での途中表示は全くないはず。
つまり、#11195の結果は出ないはず。
すると、あの結果はどうやって出したのだろう。
結果の出たあと、プログラムを書き換えてからアップした?
違う処理系での結果をN88での結果と間違えて書いた?



それはさておき。
ゆっくり入浴していたときにつらつらと思い出したこと。
大学時代の情報処理初級の授業で、丸め誤差と打切り誤差、桁落ち、情報落ちの
違い、なんてことをやったわけですよ。もはやほとんど覚えていませんがね。
そして、そういった誤差をなくすための方法として多倍長精度演算というのがある、
ということも思い出しました。こいつをやるとてきめんに遅くなるのですが、誤差も
非常に少なくなる。多倍長用のuBASICというのを知ったのは、確か私が大学を卒業
した直後ぐらいだったか。
多倍長っていうのは、例えば、1バイトに数字一桁しか格納しない、という方法。
実際の実装では、そんなことやっていたらメモリ効率が悪いので、1バイトに0から
99までの2桁の数字を格納する、なんていうのが多いかな。86のアセンブラにも
それようの命令があったんじゃないかな、BCD演算、というやつ。Z80にはあった
ような気がする。
そしてアセンブラにあるくらいだからBASICにもあるわけでして、もしかしたら上記
のuBASICがそうだったかもしれないけど、10進BASICという実装があったはず。

で、話を戻して、誤差。

> 3110  if   x < lastx  then 3070

こいつを

> 3110  if   x < lastx  then print "div=",lastx-x:goto 3070

とやってみたらどうでしょう。
1回多くループするところで、いったい何がおきているのか見えてくるかも。


11203/11135 BQO00549  konno            Re^6: PRIME88.BAS で 「169=素数?」問題
( 1) 24/04/07 20:41 11202:としきさんへのコメント コメント数:1
まとレスで失礼します。

> ダウト。
> >  23.57875633239746  43.25                  2 
> >  23.57875722543352  43.25                  2 
> もうここですでに値が異なります。
> すなわち、表示だけ倍精度、という可能性が濃厚。

うう、眠くてよく見てませんでした。(>_<)
表示だけ倍精度、が正解のようですね。(^^;

> N88の場合、仕様では、引数の型が結果の型、ということになっています。
> このプログラムでは、2.0 という単精度型で割り算をしています。
> ここを 2# としてみたら、もしかしたら違いが出てくる可能性があります。


> このプログラムを load して list をみたら、
> 3050 X = S / 2!  '; // Is there any better way to determine initial value?
> 3100      X = (X + S / X) / 2! 
> と、自動で変換されてしまっていました。

なんと! インタプリタでは精度指定の無い定数は自動的に単精度になるのですね。

> もしかしたらkonnoさんのところでも、この手の意図せざる自動変換が発生している
> かもしれません。当然、コンパイラのほうでも。
> 一度、インタプリタのほうで list をたたいて、自動変換の有無を確認されたほうが
> いいでしょう。

T-98NEXT で確認しました。やはり自動変換されます。

> よくリストを見たら、結果表示がループの外に出ている。
> 結果表示が上書きのよう、というのはそのとおりなんですが。
> 結果表示がループの外、というトリックは、やっぱりkonnoさんだった。

げげ、他のソースからコピペして行番号を変えるのを忘れてました。m(__)m
申し訳ないです。m(__)m

> 前にも書いたと思いますが、もうちょっと行番号の並びとかインデントに気を配って
> プログラムを書いていただけないでしょうか。
> バグが混入し易くなりますよ、と、繰り返しお伝えしていますよね。
> こうやって、残り少ない人生を無駄にしてしまうわけですから。

インタプリタを弄るのはもう何十年ぶりなもので、うっかりやらかしてしまいました。m(__)m
気を付けます。m(__)m

> でも、このプログラムだと、N88なら、ループ内での途中表示は全くないはず。
> つまり、#11195の結果は出ないはず。

3110番を 3118 に変更すれば正常に出力されると思うのですが
私が何か勘違いしている?

> > 3110  if   x < lastx  then print "div=",lastx-x:goto 3070
> とやってみたらどうでしょう。
> 1回多くループするところで、いったい何がおきているのか見えてくるかも。

重複部分は以下のようになりました。

div 6.226795723485168D-08  13  13          8 
div 2.220446049250313D-16  13  13          9 
SQR( 169 )= 13               13            9 

比較はほぼ間違いなく単精度でしょうね。(^^;


11204/11135 BQO00549  konno            Re^7: PRIME88.BAS で 「169=素数?」問題
( 1) 24/04/08 01:46 11203:konnoさんへのコメント コメント数:1
> 重複部分は以下のようになりました。
> div 6.226795723485168D-08  13  13          8 
> div 2.220446049250313D-16  13  13          9 

これ間違っていました。m(__)m  正しい数値を各社で比較します。

----- 単精度  -----
N88BASIC
div= 1.27316E-03             13                  13.0013            6 
TurboBasic
div= 1.272201538085938E-003  13                  13.00127220153808  6 
T-BASIC
div= 1.272201538085938E-003  13                  13.00127220153808  6 

N88BASICは精度もいまいちな感じですね。


-----  倍精度  -----
N88BASIC
div= 1.272386299866479D-03   13.00000006226796   13.00127244856782  6 
div= 6.226795723485168D-08   13                  13.00000006226796  7 
div= 2.220446049250313D-16   13                  13                 8 
div= 0                       13                  13                 9 

TurboBasic
div= 1.272386299866923E-003  13.00000006226796  13.00127244856782   6 
div= 6.226795790098552E-008  13                 13.00000006226796   7 
div= 0                       13                 13                  8 

T-BASIC
div= 1.272386299866479D-03   13.00000006226796  13.00127244856782   6 
div= 6.226795745689628D-08   13                 13.00000006226796   7 
div= 0                       13                 13                  8 

全部違うと思ったら、6回目の N88 と T が同じ数値ですね。
これでなにかわかるでしょうか。


11205/11135 CXB00940  としき           Re^8: PRIME88.BAS で 「169=素数?」問題
( 1) 24/04/08 12:28 11204:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
いろいろと見えてきたようです。

> N88BASICは精度もいまいちな感じですね。

私が仕様を知っているのはN88だけですが、N88に関していえば、まさに仕様どおり。
N88の単精度は、6桁までしか表示されないのですよ。
そして、計算されるのは7桁目まで。
他の処理系の単精度は16桁も表示されるのですね。


> ----- 倍精度 -----
> これでなにかわかるでしょうか。

いくつかわかることがあります。
まず、N88から。
前回の単なる出力結果だと、x も lastx も13で等しいのに次のループに回っている
のが不思議に思えました。でも実際には 2.220446049250313D-16 だけの差があった
わけであり、次のループに回っているのが正当でした。一方で、あまりにも差が
少なすぎたのでしょう、表示は13で打ち切られてしまっている。
ここ、私が前に書いたように print using を使えば、もしかしたら表示されていた
可能性はあります。

つぎ、TurboBasic。
N88やT-BASICだと、単精度指数の表記はEですが、倍精度指数はDを使っています。
でも、TurboBasicは、倍精度でもEで表示されている。
なんか違和感。これが仕様なんだろうなぁ。
ちなみにEは指数(exponent)の略といわれています。Dは倍(double)の略らしい。
なお、表記は同じでも値は異なっているので、計算そのものはきちんと倍精度で
行われている模様。
ところで、Wikipediaによると、指数表示でEを使うのは国際規格らしい。
実際、Excelとかでもそうなっているし。
もしかしたら倍精度でDを使うって、日本のどこかが始めたことかも。
NECとかシャープとか。
昔のMS-BASICでそうだったのかもしれないけど。

そして、T-BASICを含めて、細かい桁数の計算ではいくらかの精度差が発生すること
がわかります。
今回の話題の出発点の169が素数になってしまうという問題も、konnoさんのところの
エミュ環境のN88で起こっている話ですから、うちの実機のPC98だと、konnoさんの
ところのN88とは結果が異なる可能性がありそう。
ということで、今回の結果を出した検証プログラム、#11195に載っているものと
大体同じものだと思いますが、念のため、もう一度示してください。重要なのは表示
でして、同じような表示にしたいので表示部は必須。
なにとぞよろしくお願いします。

11206/11135 BQO00549  konno            SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/08 23:33 11205:としきさんへのコメント コメント数:1
> ということで、今回の結果を出した検証プログラム、#11195に載っているものと
> 大体同じものだと思いますが、念のため、もう一度示してください。重要なのは表示
> でして、同じような表示にしたいので表示部は必須。

DOSVAXJ3 の32ビット版をJ31モードにして TBasicインタプリタが起動できました。
結構互換性があるのね。
それで、ソースをリナンバーしてみました。
 RENUM 3000
これで、3000 から始まる行番号にキチンと並べ替えられました。\(^^)/ ヤッタ-
ではそのソースを貼り付けます。

3000 ' SQR-3.BAS
3010   DEFDBL A-Z
3020  'defsng a-z
3030 'screen 0
3040 CLS
3050 INPUT S
3060 OPEN "SQR.dat" FOR OUTPUT AS #1
3070 CC=0
3080 X = S / 2!  '; // Is there any better way to determine initial value?
3090 LASTX = 0! '; // the value one before the last step
3100 'while ( x != lastx ) '// until the difference is not significant
3110      LASTX = X 
3120      X = (X + S / X) / 2! 
3130      CC=CC+1
3140      PRINT "div=";LASTX-X, X,LASTX,CC
3150      PRINT#1,"div=";LASTX-X, X,LASTX,CC
3160  IF   X < LASTX  THEN 3100
3170  PRINT "SQR(";S;")=";X,LASTX,CC
3180  PRINT#1, "SQR(";S;")=";X,LASTX,CC
3190  CLOSE
3200  INPUT A
3210 END

このままで J31 と PC-98 で動くと思います。


11207/11135 CXB00940  としき           Re: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/09 15:06 11206:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
> このままで J31 と PC-98 で動くと思います。

ありがとうございます。
次に実家に行ったときに、このコードを走らせたいと思います。
これをこのまま、といいたいところですが、おそらく、ファイル出力のところ、
OUTPUTはAPPENDに変更させていただく予定。

あと、もともとの#11175に立ち返って。

> 条件を色々変えて試しても結果は変わらなかったのですが、ひとつだけ
> N88P.BAS
> ところがオリジナルを若干修正した以下
> PN88.BAS

#11192にも書きましたが、内部的には若干の修正ではない可能性があります。
なので、しつこくてもうしわけありませんが

> PN88.BAS
> 110  defdbl a-z                                 '倍精度指定
> ここを単精度指定にしたらどうなるか、

この結果を教えてください。
よろしくお願いいたします。


11208/11135 BQO00549  konno            Re^2: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/09 22:44 11207:としきさんへのコメント コメント数:1
> > 110  defdbl a-z                                 '倍精度指定
> > ここを単精度指定にしたらどうなるか、
> この結果を教えてください。
> よろしくお願いいたします。

もちろん 169 が素数と表示されます。
元々単精度でそういう表示になるところから始まった話題ですから。
色々試していった結果結構ソースが変わってしまいましたが。(^^;

ところで、USING を使ってみたら違いが表示されました。

1000 'pn88.bas 
1010 ' defdbl a-z                                 '倍精度指定
1020  'defdbl n                                 '倍精度指定
1030  OPEN "SQR.dat" FOR OUTPUT AS #1
1040 INPUT N
1050 IF (N/2 <> INT(N/2))=0 THEN IF N=2 THEN PRINT "素数" ELSE PRINT "合成数"
1060 J!=SQR(N) 'ELSE
1070   FOR I!=3 TO SQR(N) STEP 2
1080     IF N/I! = INT(N/I!) THEN 1100 '*EXIT1 
1090   NEXT I!
1100 '  *EXIT1
1110    PRINT USING  " .##################";I!-SQR(N) '.14
1120    PRINT#1, USING  " .##################";I!-SQR(N) '.14
1130   IF I!<=SQR(N) THEN PRINT "合成数";I!;J! 
1140   IF I!<=SQR(N) THEN PRINT#1, "合成数";I!;J! 
1150   IF I!>SQR(N) THEN PRINT "素数";I!;J!
1160   IF I!>SQR(N) THEN PRINT#1, "素数";I!;J!
1170 INPUT A
1180 END


この結果は

 .000001907350000000
素数 13  13 

このように単精度の時
I!-SQR(N)
で誤差が表示されました。
倍精度ではゼロになりました。

98実機ではどうなるでしょうね。


11209/11135 CXB00940  としき           Re^3: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/10 17:44 11208:konnoさんへのコメント コメント数:2
参照先:http://toshiki.la.coocan.jp/
> もちろん 169 が素数と表示されます。

ちょっと残念というか、当然と思えることがおきなければそれも手がかりになる
かな、と思っていたわけですよ。
それで、しつこくお尋ねしていた次第。

> ところで、USING を使ってみたら違いが表示されました。

やっぱりそうでしたか。

> 98実機ではどうなるでしょうね。

とりあえず、試したいことリスト。
すでに試し済みのものもあるかも。

#11208のpn88.bas、倍精度と単精度
#11175のPN88.BASでNを単精度にしただけのもの
そして、#11175のN88P.BASの改造版、以下。

N88P0410.BAS
100 INPUT N
110 IF N MOD 2=0 THEN ELSE *ELSE1
120     IF N=2 THEN PRINT "素数" ELSE PRINT "合成数"
130     GOTO *ENDIF1
140 *ELSE1
150     I=3
160     WHILE (I<=SQR(N)) AND (N MOD I<>0)
165         PRINT I,SQR(N)
170         I=I+2
180     WEND 
190     IF I<=SQR(N) THEN PRINT "合成数" ELSE PRINT "素数"
200 *ENDIF1
210 END

これも、Nを単精度と倍精度にしたものの2つ。
今のところ、思いつくのはこのくらい。
あ、そうだ、konnoさんのコードだとプログラム終了のところに必ずinputがあるの
ですが、これ、コンパイラだとあったほうがいいのですか?
それとも他の事情?
いえ、うちのインタプリタだと、必ず最後に入力プロンプトの「?」がはいるのが
うざいというかうっとうしくて。


11210/11135 BQO00549  konno            Re^4: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/10 21:56 11209:としきさんへのコメント コメント数:1
> そして、#11175のN88P.BASの改造版、以下。
> N88P0410.BAS

これ、実行してみました。NP2 では、169 は素数と表示されました。

> あ、そうだ、konnoさんのコードだとプログラム終了のところに必ずinputがあるの
> ですが、これ、コンパイラだとあったほうがいいのですか?

コンパイラでは終了すると画面が消えてしまい、表示の確認が出来ないのですよ。
インタプリタでは消えないんですが、ソース共通化のために入れています。


11211/11135 CXB00940  としき           Re^5: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/10 23:25 11210:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
> これ、実行してみました。NP2 では、169 は素数と表示されました。

あ〜、いやいや、そこではなくて。
いや、そこなのか?
#どっちだよ

ループの最後というか、誤判定されるわけですよね。
その、最後とそのもうひとつ前というか、単精度型と倍精度型でどうなっているのか
見たいな、ということです。

プログラム最後のinputについては了解しました。
やはり、環境によって、こういう差異が発生するものなのですね。
想像はできても、実際にお話を聞けたことがありがたいというか。


11212/11212 DGF01024  めざら           DOSVAXJ3 JP240410 更新
( 1) 24/04/11 05:56 コメント数:2
参照先:http://mezala.la.coocan.jp/
DOSVAXJ3 が 240410版に更新されました。
以下更新内容です。

build JP240410 (2024/4/10)
・J-3100モードが動作していなかったのを修正しました。
・Linux, macOS でビルドできなくなっていたのを修正しました。

……ということなんで,われわれにはあまり関係ないかな(^^;

11213/11135 BQO00549  konno            Re^6: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/11 20:13 11211:としきさんへのコメント
> ループの最後というか、誤判定されるわけですよね。
> その、最後とそのもうひとつ前というか、単精度型と倍精度型でどうなっているのか
> 見たいな、ということです。

実行結果(数値はVTDOSの結果を張り付けたが表示は同じ)
? 169
 3             13
 5             13
 7             13
 9             13
 11            13
 素数

NP2の結果は単精度型は「素数」、倍精度型は「合成数」と表示だけ違います。

110番の THEN ELSE はこれでいいんでしょうか。
まあ 2 の表示を省いたのだと思うけど。

> 110 IF N MOD 2=0 THEN ELSE *ELSE1


11214/11212 BQO00549  konno            Re: DOSVAXJ3 JP240410 更新
( 1) 24/04/11 21:05 11212:めざらさんへのコメント
> DOSVAXJ3 が 240410版に更新されました。

更新されていたのですね、お知らせいただきありがとうございます。

> build JP240410 (2024/4/10)
> ・J-3100モードが動作していなかったのを修正しました。
> ・Linux, macOS でビルドできなくなっていたのを修正しました。

うげ、今ちょうど J31モードを使っている所なんですよね。
それで、3月15日に更新があったのは知っていたのですが、32ビット版は落としてなかった。OTL
ちなみに、3月15日の更新内容は

---------------------------------------------------------------
build JP240315 (2024/3/15)

    J-3100 ビデオモード 64h (640×400 2色 文字 80×20)に対応しました。
    MS-DOS/V 6.2 をイメージファイルからブートした場合に jkeyb.sys の /106 設定が有効にならず
    英語キーボード配列になっていたのを修正しました。
    [dosbox] kanjikey を追加しました。漢字キーを ALT+半角全角、半角全角、右 ALTに割り当てる事ができます。
    int 21h ah=5ch に対応しました。Windows 3.1 用の MS-Office が起動可能になります。
    内蔵 BIOS 割り込みのエントリアドレスを F000:C000 以降に変更しました。

---------------------------------------------------------------

> J-3100 ビデオモード 64h (640×400 2色 文字 80×20)に対応しました。

これは、20行表示モードが使えるということかと思って VZJ31の ^KL でやってみました。
が、白画面が真っ黒になって、縦400ドットが、480ドットに伸びました。
カーソルは動きますが、文字は全く表示されません。
もう一度 ^KL で元に戻りましたが、これは使えないようです。
CHEV 64 でも同じ結果です。
黒画面はどうも VGA ぽいですね。

うーん、私の設定か解釈が間違っているのでしょうか。軟式さんに聞いてみようかしら。

それはともかく、これがきっかけで J31 用のBASICコンパイラを試してみたら
なんと! 生成した実行ファイルが VTDOS で動くではないですか。\(^^)/ ヤッタ-
MS-DOS Player と同じく テキスト表示だけなら問題なく動作します。
この実行ファイル一つで、VTDOS、MS-DOS Player、DOSVAXJ3のVGA,J31モード全部動きます!!

> ……ということなんで,われわれにはあまり関係ないかな(^^;

関係ないどころか、埋もれていたお宝が完全復活しました!!
それだけではなく、今までのエミュの壁を突破できる切り札として蘇ったのです!!

これはめざらさんのおかげですね。ありがとうございます。
としきさんとの素数プログラムのやりとりも助けになっています。
軟式さんの J31モードのまめな更新のおかげで、古代の遺産が復活出来ました!
みなさまに感謝です。m(__)m

# 伝説巨神 出でよん 発動編(壮絶な戦いになりそうな悪寒)


11215/11135 CXB00940  としき           Re^4: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/13 01:13 11209:としきさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
> とりあえず、試したいことリスト。

試してきました。

> #11208のpn88.bas、倍精度と単精度

pn88単精度
 .000000000000000000
合成数 13  13 

pn88b倍精度
 .000000000000000000
合成数 13  13 

> #11175のPN88.BASでNを単精度にしただけのもの

合成数と出ました。

> そして、#11175のN88P.BASの改造版、以下。

単精度でも倍精度でも同じ、

 3             13 
 5             13 
 7             13 
 9             13 
 11            13 
合成数

と出ました。単精度でも倍精度でも同じです。
うむ、興味深いぞ。

> 190     IF I<=SQR(N) THEN PRINT "合成数" ELSE PRINT "素数"

Iも13、SQR(N)も13なのだから、合成数と表示されるのが正当。
そして実際、うちでは想定どおり動いています。
ところが、konnoさんのところでは、単精度型ではこの比較式が成り立たず、ELSEに
落ちてしまっている。そして、倍精度型ではきちんと動いている。
なんか、エミュの挙動がおかしいとしか思えない。
前にも書きましたが、N88BASICの仕様では、関数の結果は引数と同じ型になることに
なっています。つまり、Nが単精度ならSQR(N)の結果も単精度のはず。だから、小数点
以下の細かいところの値が出てくることがおかしい。
もしかしたら、次のような簡単なプログラムでも、実機とエミュで差が出たりして。

10 A#=1.23456789#
20 B!=A#
30 PRINT A#,B!

これ、実はN88のマニュアルに載っているサンプルです。
そして、仕様上のこの実行結果は

RUN
1.23456789  1.23457

となるべきなのだそうです。
もしエミュでこうならないとしたら、それはどこかがおかしい。
エミュの作者に調査を依頼してもいいかも。



追伸
#11213

> 110番の THEN ELSE はこれでいいんでしょうか。
> 110 IF N MOD 2=0 THEN ELSE *ELSE1

N88BASICでは、言語仕様として、THEN節に空文を許します。
つまり、THEN のときは、何もせずに、次の行に進むことになります。
これ、#11169で触れているとおりです。


11216/11135 BQO00549  konno            Re^5: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/13 22:03 11215:としきさんへのコメント コメント数:1
> これ、実はN88のマニュアルに載っているサンプルです。
> そして、仕様上のこの実行結果は
> 
> 1.23456789  1.23457
> 
> となるべきなのだそうです。

NP2でやってみた結果です。

 1.23456789    1.23457

表示は全く同じですね。やっぱり表示と内部の数値がズレているのかなぁ。
他のエミュの結果は全て以下の数値でした。

 1.23456789    1.234568

98エミュの表示が上の数値で内部的には下の数値だとしたら、計算が合わないのも合点ですね。
でも何故こうなるのかがわからないので、とっても気になります。

> もしエミュでこうならないとしたら、それはどこかがおかしい。
> エミュの作者に調査を依頼してもいいかも。

表示は全く同じなので、おかしくないということですね。(違う!)

> N88BASICでは、言語仕様として、THEN節に空文を許します。
> つまり、THEN のときは、何もせずに、次の行に進むことになります。
> これ、#11169で触れているとおりです。

なるほど、つまり想定どうりということですね。


11217/11212 BQO00549  konno            DOSVAXJ3 JP240410 20行表示がおかしい?
( 1) 24/04/13 23:28 11212:めざらさんへのコメント
> それで、3月15日に更新があったのは知っていたのですが、32ビット版は落としてなかった。OTL

実は寝室のPCでダウンロードしていました。(^^;
ダウンロードだけして寝落ちしてそのまま忘れていたようです。(^^;;
ということで

> build JP240410 (2024/4/10)
> ・J-3100モードが動作していなかったのを修正しました。

これがどういうことかと疑問だったので確認してみました。
・・・J31モードにすると、起動中に固まってしまいました、(>_<)
そういうことでしたか・・・

> > J-3100 ビデオモード 64h (640×400 2色 文字 80×20)に対応しました。
> これは、20行表示モードが使えるということかと思って VZJ31の ^KL でやってみました。
> が、白画面が真っ黒になって、縦400ドットが、480ドットに伸びました。
> カーソルは動きますが、文字は全く表示されません。
> もう一度 ^KL で元に戻りましたが、これは使えないようです。
> CHEV 64 でも同じ結果です。

これ、CHEJ 64 だとモードが変わりました。
CHEV コマンドに反映されていないみたいです。デジャブのような。(^^;

D:\NC>chev 64

V - Video mode information    R1.0  (C)ChaN,1993

Current Video Mode = 74h
Screen Size        = 80x25
Character Height   = 16
VRAM Mode          = A/N
VRAM Address       = B800:0000 (Real VRAM)

それで、CHEJ コマンドを試したら

D:\NC>chej 64
CHEJ.EXE <MultiMode CHEV> ver 6.10 by Natrium.

J-3100(DCGA)、日本語環境に切り替えました。
現在のビデオモードは 64h です。

V - Video mode information    R1.0  (C)ChaN,1993

Current Video Mode = 64h
Screen Size        = 80x20
Character Height   = 20
VRAM Mode          = A/N
VRAM Address       = B800:0000 (Real VRAM)

おお、画面モードが 20行に変わりました。
それで、VZJ31 の編集画面を見ると
行数は 25行のまま、アンダーラインカーソルも追随します。
点滅カーソルは 20行になったようで、下に行くほどズレます。

うーむ、これは VZが対応できていないのかしら?
やっぱり軟式さんに聞いてみようかな。


11218/11135 CXB00940  としき           Re^6: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/14 12:14 11216:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
> NP2でやってみた結果です。
> 他のエミュの結果は全て以下の数値でした。
> 表示は全く同じなので、おかしくないということですね。(違う!)

NP2と他のエミュで差が出る、というところは一つの突破口かも。
少なくともNP2以外のエミュは仕様どおりではないということで、バグ報告は可能
だと思います。おそらく、四捨五入するときの桁数を誤っていると想定されます。
仕様上は、有効桁7桁、出力のときは7桁目が四捨五入されて6桁で表示、という
ことになっているのですから。
なので、以後は、NP2と実機の差異をどうするか。
どうも、本来は7桁以上は格納してはいけないものを7桁以上格納している、その上
7桁以上で比較してはいけないものを7桁以上で比較している、というように見える
わけですよ。
print usingを使う以外に、何かいい方法はあるかなぁ。


実際、この程度の小数の誤差がどの程度影響するかはわかりませんがね。
でも、もしかしたら、昔からゲームなんかでも使われている可能性はあるわけで。
konnoさんは、例えばバルーンパンチなんてゲームを覚えておられませんかね。
シーソーに乗った人が交互にジャンプして上のほうで動いている風船を割っていく、
というゲームです。
このゲームで飛んでいる人間は、まるで重力で引かれるような感じで頂点に向かって
減速して、また落下するときは加速するわけです。このゲームに限らず、まるで重力
に引かれたような動きをする、だとか、慣性が働いているようになかなか加速しない
上に速度が乗ったらすぐには止まれない、といった動きをするようなゲームでは、
もしもそれなりに理論的なアルゴリズムを使うならば、物体の位置決定に二次関数を
使う必要があるわけです。実際に使っているアルゴリズムがどこまで理論的に正しい
ものになっているかはわかりませんけどね。
そして、二次関数を解くためにはSQR関数が必要。
あるいは、ゲームによっては三角関数を使っているものもあるかもしれない。
そして、画面のXとYの座標は当然整数。
ときどき、当たり判定がバグっているゲームというのが話題になることがありますが、
あれっていうのはもしかしたら、小数と整数の比較の際の誤差の問題かも。そして、
実機だと正常に動いていたのにエミュだとおかしい、というゲームなどがあった場合、
それこそこのような小数の誤差の可能性は高いかも。
もちろん、倍精度を使えば誤差は少なくなりますが、リアルタイムの計算の場合、
倍精度だとやっぱり重くなるので、たいていは単精度を使うでしょうし。


11219/11135 BQO00549  konno            Re^7: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/15 01:15 11218:としきさんへのコメント コメント数:1
> NP2と他のエミュで差が出る、というところは一つの突破口かも。
> 少なくともNP2以外のエミュは仕様どおりではないということで、バグ報告は可能
> だと思います。おそらく、四捨五入するときの桁数を誤っていると想定されます。
> 仕様上は、有効桁7桁、出力のときは7桁目が四捨五入されて6桁で表示、という
> ことになっているのですから。

もしかしたら誤解させてしまったかもしれません。
他のエミュとは、98エミュ以外の、J31とかDOS/V系のエミュのことです。
今回 NP2以外の98エミュは確認していません。同じ結果になると思ったので。

ということで、ANEX86 や T98-NEXT のN88コンパイラ、インタプリタでも確認しました。
結果は NP2と 表示は全く同じでした。

> どうも、本来は7桁以上は格納してはいけないものを7桁以上格納している、その上
> 7桁以上で比較してはいけないものを7桁以上で比較している、というように見える
> わけですよ。

これが実際どうなのかはわかりませんが、BASICのルーツは MSのGW-BASICだと思います。
T-BASICなどは漢字処理を覗けば恐らくほとんどそのままの互換性だと思っているのですが
NECのN88BASICは、あちこち変えているようですが、単精度の精度もわざと落としているように見えます。
その辺がエミュでの誤動作の原因になっているのではないかと愚考します。

> konnoさんは、例えばバルーンパンチなんてゲームを覚えておられませんかね。
> シーソーに乗った人が交互にジャンプして上のほうで動いている風船を割っていく、
> というゲームです。

私はこの手のゲームはあまりやっていないので覚えていません。

> ときどき、当たり判定がバグっているゲームというのが話題になることがありますが、
> あれっていうのはもしかしたら、小数と整数の比較の際の誤差の問題かも。そして、
> 実機だと正常に動いていたのにエミュだとおかしい、というゲームなどがあった場合、
> それこそこのような小数の誤差の可能性は高いかも。

今回のことを踏まえるとそう考えられますね。

> もちろん、倍精度を使えば誤差は少なくなりますが、リアルタイムの計算の場合、
> 倍精度だとやっぱり重くなるので、たいていは単精度を使うでしょうし。

N88BASICは8ビット時代の互換性重視ではないかと思いますが、8ビットの貧弱なCPUで
ゲームの速度を上げるためにわざと単精度の桁を落としたのではないかと思います。
そして、16ビット版になっても互換性のためにそこを変えることが出来なかったのかも。


11220/11135 CXB00940  としき           Re^8: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/15 13:56 11219:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
> もしかしたら誤解させてしまったかもしれません。
> 他のエミュとは、98エミュ以外の、J31とかDOS/V系のエミュのことです。

はい、誤解しました。
続報をいただいたことで、誤解は氷解しました。

> NECのN88BASICは、あちこち変えているようですが、

うん、まぁ、その前のN-BASICからの互換性というのがありますからね。
そちらのほうでいろいろと変えていたところはあるかもしれません。

> 単精度の精度もわざと落としているように見えます。

こちらについてはどうなんだろう。
そうではないというわけではなく、根拠不足というか、これまでのところでは、私
にはそう思えるだけの挙動はないような気がしています。
ということで、ちょっと調べてみました。
まず、単精度は4バイトであらわす実数、倍精度は8バイトであらわす実数。
これは、調べた範囲では、どこも同じみたい。80年代の8ビットパソコンのBASIC
でも、21世紀の64ビットパソコンのCコンパイラでもおおむね一緒。
ところが、倍精度のほうが、最近の国際規格とN88BASICで異なるみたい。
#11164に書いたように、N88BASICでは倍精度の扱える上限は 1.7*10^38 ですが、
最近の規格では 1.8*10^308 まで扱えるらしい。
一方で単精度の方は最近の規格でも 1.7*10^38 で同じ。
内部表現についても、仮数部23ビット、指数部8ビット、符号1ビットという部分
に変化はない。
でも、だからN88の単精度では精度を落としていないかというといささか怪しいと
いうか断言はできない。
なにかというと、十進数との変換部分。
#11135にも書きましたが、仕様としては有効桁7桁、出力のときは7桁目が四捨五入
されて6桁で表示、となっているわけですよ。でも、他の処理系では例えば、有効桁
7桁で表示も7桁、となっているかもしれない。もしそうであれば少なくとも見かけ
の精度は落ちているわけです。あるいは、他の処理系では、7桁目で四捨五入では
なく切り捨て表示となっているかもしれないし。
ただ、あまりにも他のマシンと差があるようであれば、当時、大騒ぎになっている
のではないかなぁ。あの時代、ネットはなくてもパソコン雑誌はあったし、8ビット
のころはともかく16ビットの時代はパソコン通信もあったし。
ということで、とりあえず現時点では根拠不足としてkonnoさんのご意見に賛同は
しないでおきます。
#つまり、何かあればすぐに意見は変わる

ただ、エミュという意味では、よく言われる「バグまで再現した」というものが評価
が高いわけで、現状、実機と差異が出るエミュは、完成度としてはもう一歩、という
のが現実的な評価だと思われます。


11221/11135 BQO00549  konno            Re^9: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/16 00:04 11220:としきさんへのコメント コメント数:1
> 続報をいただいたことで、誤解は氷解しました。

紛らわしい表現で誤解させてしまい申し訳ないです。
とりあえずホッとしました。

> > 単精度の精度もわざと落としているように見えます。

考えてみたら、これは表示だけなのかもしれませんね。
N88BASICは、インタプリタもコンパイラも中間コードの LIB を使用しているように見えます。
ということは、そのバイナリコードは BIOS.ROM の中なのではないですか。

私の手持ちのNP2の BIOS.ROMは、実機のものではなく、互換BIOS かもしれません。
その互換BIOSを作る時、N88BASICの仕様に忠実に作るために、#11215

> 10 A#=1.23456789#
> 20 B!=A#
> 30 PRINT A#,B!
>
> これ、実はN88のマニュアルに載っているサンプルです。
> そして、仕様上のこの実行結果は
>
> RUN
> 1.23456789 1.23457
>
> となるべきなのだそうです。

この結果を忠実に再現するために、わざと内部数値まで桁落ちさせたのではないかと疑い始めました。
つまり、問題なのは、互換BIOS.ROM なのかもしれないと思うようになりました。

これは、実機を持たない人たちにとって無くてはならない非常にありがたい福音ですが
互換BIOS を作ったのは、著作権の問題回避の為なので、バイナリレベルで違うものでなければならないわけです。
もしかしたら、この部分がそのための直せない生贄だったりして。あくまで妄想ですが。

> ただ、エミュという意味では、よく言われる「バグまで再現した」というものが評価
> が高いわけで、現状、実機と差異が出るエミュは、完成度としてはもう一歩、という
> のが現実的な評価だと思われます。

NP2は、細部の再現性にこだわったエミュという評価があるようなのですが
先のサンプルプログラムの結果は忠実に再現していますね。(^^;


11222/11135 CXB00940  としき           Re^10: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/16 12:22 11221:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
> ということは、そのバイナリコードは BIOS.ROM の中なのではないですか。

確かに .LIB のファイルのサイズが小さ目というところから、実際に LIB がやって
いることは ROM の中身の呼び出しのみ、という可能性は高そうです。

> この結果を忠実に再現するために、

ある意味、この結果「だけ」を忠実に再現している、という感じ。
もし「実機を忠実に再現」するのであれば、169は合成数と表示される必要がある。
この点がなされない限り、実機に対するエミュとしての完成度は今一歩、という
ところで終わってしまいそうです。
もっとも世の中には、既知のバグどころか未知のバグまで再現したエミュレータと
いうものもある模様。実機で新たなバグが発見されてから、エミュレータでも同じ
バグが発現した、なんて話もあるようで、とても不思議。こういうのが、いわゆる
「完璧なエミュレータ」というやつでしょう。なぜ作れるんだろう。

> 互換BIOS を作ったのは、著作権の問題回避の為なので、

これはそのとおりだと思いますが、その一方で、実数のバイナリ表現というものは
ある意味で規格化されているわけです。つまり、実数演算とかバイナリと十進数の
変換とかの部分は世の中にいくらでもサンプルコードとかライブラリとかのフリーで
使えるものが存在しているわけで、そしてそういうものを使えば少なくとも著作権の
問題は回避できるはず。さらに、その手のコードって世界中の人が見ているわけです
から、精度を落とす方向にいじることは少ないのではないかなぁ。というか、わざと
精度を落とす、なんてことに時間をかけるくらいならとっととリリースしてくれよ、
という気もする。
もちろん、そういうものを使わずに1からコードを書いていたら、十分な精度を確保
できていなくても不思議はないけど。
あ、でも、ありうるかな。
倍精度のほうが現在のありふれたものとは内部表現が異なっているようだから、そちら
のほうに合わせて、ということはあるかも。



実は私、実数演算についてはちょっとだけやかましい。
#2066とか#10367にも書いたけど、大昔、8ビットマシンの時代、実数演算のマシン語
ルーチンを書いてハンドアセンブルしていたもので。
といっても四則演算だけですけどね。


11223/11135 BQO00549  konno            Re^11: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/16 23:58 11222:としきさんへのコメント コメント数:1
> もっとも世の中には、既知のバグどころか未知のバグまで再現したエミュレータと
> いうものもある模様。実機で新たなバグが発見されてから、エミュレータでも同じ
> バグが発現した、なんて話もあるようで、とても不思議。こういうのが、いわゆる
> 「完璧なエミュレータ」というやつでしょう。なぜ作れるんだろう。

それはきっと、リバーs^ ・・・ いや、なんでもないです。(^^;

> 実は私、実数演算についてはちょっとだけやかましい。
> #2066とか#10367にも書いたけど、大昔、8ビットマシンの時代、実数演算のマシン語
> ルーチンを書いてハンドアセンブルしていたもので。
> といっても四則演算だけですけどね。

鶴亀算みたいなものでしたっけ? 結構面倒くさいんですよね。
丁度 DANNYさんの浮動小数演算ライブラリを目にしていたので見てみました。
ASMは1531行ありましたね。
バイナリは恐らく2千バイトくらいになるのかなぁ。

J3100用BASICコンパイラの続報も書かなくてはいけないのでこの辺で。


11224/11135 CXB00940  としき           Re^12: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/17 02:14 11223:konnoさんへのコメント コメント数:1
参照先:http://toshiki.la.coocan.jp/
konnoさん、なんか他のものを連想している。

> 鶴亀算みたいなものでしたっけ? 結構面倒くさいんですよね。

鶴亀算は整数演算です。
何だろう、何と勘違いしたんだろう。おいらにはわからない。


11225/11135 BQO00549  konno            Re^13: SQRの単精度と倍精度の表示検証ソース
( 1) 24/04/17 23:21 11224:としきさんへのコメント
> 鶴亀算は整数演算です。
> 何だろう、何と勘違いしたんだろう。おいらにはわからない。

あう、多分整数演算の事だと思います。(>_<)
私は算数も数学も苦手というか、数字の計算や記憶が全くダメなんですね。
だからパソコンにやらせようと思うのです。(^^;