#N88BASIC
dim i1 as integer
dim a1,a2 as single
dim l1,l2 as long
dim q1,q2 as int64
dim x,y as double
i1=3.14
l1=2^50
a1=1+10^-10
a2=10^-100
q1=2^60+1
q2=q1-2^60
x=a1/0
というプログラムの実行結果です。 (AB_4.10.00)
「デ」はデバッグモード実行、リはリリースコンパイル。
デ リ 正しい結果 備考
i1=3.14 3 3 デは、整数なのに小数以下も代入できている。
l1=112589990684262 0 計算エラー longの最大値(2147483647)より大きい数値が代入された。
a1=1.0000000001 -9 1.0 単精度に代入した時点で情報落ちを起こし1.0となる。
デは、有効7桁以上保持しているし、
リに至っては意味不明。
a2=0 -100 ゼロ 単精度に代入した時点で無限小と判定されゼロとなる。
リの計算結果は意味不明。
q1=約4.6e18 ゼロ 2^60+1(約1.15e18) int64以下の範囲内なので整数で表せるはず。
ついでに、print文はintが相手のときは整数表示できる
筈なのに実数標記 (fortranでいうE変換標記)になっている。
q2=0 約-1.15e18 1 デは桁落ちしている。リはq1がコケているため異常反応。
int64の範囲内なので桁落ちは起こさないはず。
y=永久ループ 0 ゼロ割りエラー これは、勝手にゼロで置き換えないでほしい。
以上のとおり、計算誤差が生じない筈のところで計算誤差が生じたり、
変数の型からして記憶できない筈の値が記憶されていたり、
デバッグモードとリリースモードでまるで違う計算結果が生じたりと、
悲惨な結果になりました。
おそらく、「数値は全て倍精度で計算している」というような大チョンボをやっている可能性が大きい
ものと思われます。
単純な計算の筈が
[AB]にはOn Error命令が実装されていないので、計算エラーがうまくいかないようです。機能強化に要望します?
あと#strictを付けてデバッグコンパイルすると分かりますが・・・
基本的に数値項目は
整数:Long
小数の桁が少ない:Single
小数の桁が多い :Double
のようです。ヘルプではDouble型って書いてあったような気がします!
一般的に計算は、右辺の最大精度で計算し結果を左辺の型に変換して代入します。
また負のべき乗は、括弧を付けないと正しく式を判定できないようです。
この件も、改善依頼します?
(自分の経験では、計算順番はコンパイラに依存しないようにする為に、式は必ず括弧で囲むってのがあります・・・)
以下のようにコードを書き換えると、エラー以外は実行出来ると思います。
Print命令に数値を指定すると、Double型として変換しますのでInt64が正しく表示できるかわかりません。
あと#strictを付けてデバッグコンパイルすると分かりますが・・・
基本的に数値項目は
整数:Long
小数の桁が少ない:Single
小数の桁が多い :Double
のようです。ヘルプではDouble型って書いてあったような気がします!
一般的に計算は、右辺の最大精度で計算し結果を左辺の型に変換して代入します。
また負のべき乗は、括弧を付けないと正しく式を判定できないようです。
この件も、改善依頼します?
(自分の経験では、計算順番はコンパイラに依存しないようにする為に、式は必ず括弧で囲むってのがあります・・・)
以下のようにコードを書き換えると、エラー以外は実行出来ると思います。
コード: 全て選択
#N88BASIC
#strict
dim i1 as integer
dim a1 as single , a2 as single
dim l1 as long , l2 as long
dim q1 as int64 , q2 as int64
dim x as double , y as double
i1=3.14
l1=2^50
a1=1+(10^(-10))
a2=(10^(-100))
q1=(2 ^ 60 ) As Int64 +1
q2=q1-(2 ^ 60) As Int64
x=a1/0
>[AB]にはOn Error命令が実装されていないので、計算エラーがうまくいかないようです。機能強化に要望します?
これは、明白な「バグ」であるので書いたのです。
以下、ゼロ割りを例にとります。
理由の1
デバッグモードとコンパイルモードで結果が違うということは、デバッグモードの存在意義が無くなるため。
理由の2
IEEE754の基準に違反しているため。
http://www.ma.is.saga-u.ac.jp/minamoto/doc/kyudai.pdf
9ページ。
まあ、ABはIEEE754準拠とはどこにも書いてないのですが、
準拠していないともどこにも書いてありません。
(この点、十進BASICとは明確に異なる。)
なお、IEEE754では以下の通り。
※マニュアル未記載ですが、ABの実数の内部形式はIEEE754です。
※※IntesCPUはIEEE754にしたがっているため。
ゼロ割り:±Inf
無効演算(√-1,log(-1)など):NaN(非数値)
※InfやNaNは、特殊な数値であり、以降の計算でInfやNaNを含む演算はInfやNaNとなる。
ですから、
セロ割りが生じた場合、
ゼロ割りエラーで停止(N88Basicの動作) または
±Infとして計算続行 (当然ながら、Infを含んだ演算はInfやNaNを返すものとする。)
のいずれかなら正しい結果です。
※Print x/0 などについても、Inf として出力されることに注意。
でも、現状は、
・デバッグモードの永久ープ:論外。
・コンパイルモ-ドで答=0:論外。数学として間違っている。
としか言いようがないです。
ON ERROR 文は、こういうチョンボからみればどうでもいいツマラナイ状況です。
※※IEEE754準拠を徹底的につきつめると、
・IntelCPUは超越関数に対し1.5bit以内の誤差の計算結果を保証する
となるけど、ABはここまでの保証ナシ、ですよね?
(IntelCPUは80bitで計算しているが1.5bit以内の誤差が確保できる程度。
よって、64bitで計算しているABは1.5bit以上の計算誤差が発生する。)
これは、明白な「バグ」であるので書いたのです。
以下、ゼロ割りを例にとります。
理由の1
デバッグモードとコンパイルモードで結果が違うということは、デバッグモードの存在意義が無くなるため。
理由の2
IEEE754の基準に違反しているため。
http://www.ma.is.saga-u.ac.jp/minamoto/doc/kyudai.pdf
9ページ。
まあ、ABはIEEE754準拠とはどこにも書いてないのですが、
準拠していないともどこにも書いてありません。
(この点、十進BASICとは明確に異なる。)
なお、IEEE754では以下の通り。
※マニュアル未記載ですが、ABの実数の内部形式はIEEE754です。
※※IntesCPUはIEEE754にしたがっているため。
ゼロ割り:±Inf
無効演算(√-1,log(-1)など):NaN(非数値)
※InfやNaNは、特殊な数値であり、以降の計算でInfやNaNを含む演算はInfやNaNとなる。
ですから、
セロ割りが生じた場合、
ゼロ割りエラーで停止(N88Basicの動作) または
±Infとして計算続行 (当然ながら、Infを含んだ演算はInfやNaNを返すものとする。)
のいずれかなら正しい結果です。
※Print x/0 などについても、Inf として出力されることに注意。
でも、現状は、
・デバッグモードの永久ープ:論外。
・コンパイルモ-ドで答=0:論外。数学として間違っている。
としか言いようがないです。
ON ERROR 文は、こういうチョンボからみればどうでもいいツマラナイ状況です。
※※IEEE754準拠を徹底的につきつめると、
・IntelCPUは超越関数に対し1.5bit以内の誤差の計算結果を保証する
となるけど、ABはここまでの保証ナシ、ですよね?
(IntelCPUは80bitで計算しているが1.5bit以内の誤差が確保できる程度。
よって、64bitで計算しているABは1.5bit以上の計算誤差が発生する。)