新しく発言する EXIT インデックスへ
数値の丸め(JISZ8401新版対応)

  数値の丸め(JIS Z8401新版対応) 河川屋 2005/08/18 00:17:49 
  FullBASIC(JISX3003)のROUND関数は, 白石 和夫 2005/08/18 09:29:00 
   ├100DECLAREEXTERNALFUNCTIONROUND 白石 和夫 2005/08/18 10:01:47 
   ├100REM偶数丸めJISZ8401(A) 白石 和夫 2005/08/18 21:08:30 
   └>PRINTUSINGは,ROUND(x,n)を適用して丸め... 河川屋 2005/08/26 20:56:58 
    ├FullBASICのROUND関数は 白石 和夫 2005/08/26 22:13:14 
    └誤解があるようなので,補足。 白石 和夫 2005/08/26 23:11:12 

  数値の丸め(JIS Z8401新版対応) 河川屋 2005/08/18 00:17:49  ツリーへ

数値の丸め(JIS Z8401新版対応) 返事を書く
河川屋 2005/08/18 00:17:49
数値の丸め方について

LET x=-1.5
print using "###": x   結果: -2
print round(x,0) 結果: -1

print usingでもroundでも四捨五入による丸めだから、答は一致する筈
であるところ、上記のように一致しません。
発生状況:
1.xが負である。
2.上方丸めと下方丸めの距離がちょうど等しい。
の2条件を満たした場合に発生。

ちなみに、JIS Z8401:1999(数値の丸めかた)では、
規則A:2進モード時の拡張ROUND関数と等価。いわゆる五捨五入。
規則B:四捨五入と等価。
であり、どちらの場合も、
「絶対値をとってから適用する」
とあります。
よって、
・print usingはJISどおり、
・roundはJISとおりでない
ということになっています。
http://www.jisc.go.jp

注:JIS Z8401の規則Bは1999年に追加された。
   このため、BASIC(JIS X3003:1993)の規則
   策定以降のJIS変更という関係にあり、後続規定優先と考えると、
   round関数が誤動作していることになります。
   また、JIS X3003を優先させると解釈しても、
   ・丸めを伴う関数により結果が異なり、そのことについて注記が無い。
   ということが問題が残ります。
  

  FullBASIC(JISX3003)のROUND関数は, 白石 和夫 2005/08/18 09:29:00  ツリーへ

Re: 数値の丸め(JIS Z8401新版対応) 返事を書く
白石 和夫 2005/08/18 09:29:00
Full BASIC(JIS X 3003)のROUND関数は,
ROUND(x,n)=INT(x*10^n+.5)/10^n
で定義されています。J
また,規格上,PRINT USINGは,ROUND(x,n)を適用して丸めるようには指示されていません。
JIS X3003の改定を働きかけていただけるとよいと思います。(ヘルプにも少し書いてありますが,JIS X3003には細部で不備があります)
なお,ROUNDは予約語ではないので,外部関数定義を利用して異なる動作をするように変更して使うことは可能です。

   ├100DECLAREEXTERNALFUNCTIONROUND 白石 和夫 2005/08/18 10:01:47  ツリーへ

Re: FullBASIC(JISX3003)のROUND関数は, 返事を書く
白石 和夫 2005/08/18 10:01:47
100 DECLARE EXTERNAL FUNCTION ROUND
110 PRINT ROUND(-1.5,0)
120 END
130 EXTERNAL FUNCTION MyROUND(x,n)
140 IF x>=0 THEN
150 LET MyROUND=ROUND(x,n)
160 ELSE
170 LET MyROUND=-ROUND(-x,n)
180 END IF
190 END FUNCTION
200 EXTERNAL FUNCTION ROUND(x,n)
210 DECLARE EXTERNAL FUNCTION MyROUND
220 LET ROUND=MyROUND(x,n)
230 END FUNCTION

   ├100REM偶数丸めJISZ8401(A) 白石 和夫 2005/08/18 21:08:30  ツリーへ

Re: FullBASIC(JISX3003)のROUND関数は, 返事を書く
白石 和夫 2005/08/18 21:08:30
100 REM 偶数丸め JIS Z8401(A)
110 DECLARE EXTERNAL FUNCTION ROUND
120 PRINT ROUND(1.5,0)
130 PRINT ROUND(-1.5,0)
140 PRINT ROUND(2.5,0)
150 PRINT ROUND(-2.5,0)
160 PRINT ROUND(3.5,0)
170 PRINT ROUND(-3.5,0)
180 PRINT ROUND(4.5,0)
190 PRINT ROUND(-4.5,0)
200 PRINT ROUND(-12.25,1)
210 PRINT ROUND(-12.35,1)
220 PRINT ROUND(135,-1)
230 PRINT ROUND(-135,-1)
240 END
250 EXTERNAL FUNCTION RoundSub(x) ! 偶数に丸める
260 IF x<0 THEN
270 LET RoundSub=-RoundSub(-x)
280 ELSEIF FP(x)<0.5 OR FP(x)=0.5 AND MOD(IP(x),2)=0 THEN
290 LET RoundSub=IP(x)
300 ELSE
310 LET RoundSub=IP(x)+1
320 END IF
330 END FUNCTION
340 EXTERNAL FUNCTION ROUND(x,n)
350 DECLARE EXTERNAL FUNCTION RoundSub
360 LET n=ROUNDsub(n)
370 LET ROUND=RoundSub(x*10^n)/10^n
380 END FUNCTION

   └>PRINTUSINGは,ROUND(x,n)を適用して丸め... 河川屋 2005/08/26 20:56:58  ツリーへ

Re: FullBASIC(JISX3003)のROUND関数は, 返事を書く
河川屋 2005/08/26 20:56:58
>PRINT USINGは,ROUND(x,n)を適用して丸めるようには指示されていません。
>JIS X3003の改定を働きかけていただけるとよいと思います。
>(ヘルプにも少し書いてありますが,JIS X3003には細部で不備があります)
いえ、こういうのは、別に不備(というか矛盾)とは解していないのです。
(本業のほう(土木設計の各種設計基準)の矛盾からみればこんなのは無矛盾みたいなもの。)

まず、PRINT USINGとROUNDの関係ですが、
ROUNDは厳密な定義、PRINT USINGは負値の扱いで2通りの解釈が可能。
とすると、他の箇所で矛盾が生じる箇所が多いほうが解釈の誤り。
この場合、PRINT USINGとROUNDを同じと解釈しても違うと解釈
してもJISX3003の他の記述には影響なし。ということは、
わざわざ、別物と解釈するのは、同じと考えるのより感覚が異常だというのが残るから、
PRINT USINGとROUNDは同じであると推定。
(推定は法律用語における意味で使っている。推定は、
 反証を示さない限り推定したことを覆すことはできない。
 たとえば、マニュアルに、「十進BASICとしてはこういう解釈
 で組んでいる」と書いてあれば、そういうものだと定義されていることになる。)
 ※だってえ、他の細かい解釈の相違についていろいろ書いてあるから。
  
次に、数値の丸めについて、8401と3003の違いをどう解釈するか。
まず、3003はBASICだけに有効、8401は工業規格全体に有効だから、
こと数値丸めに関する限り、8401が上位規格であるのは間違いないところ。
よって、
規格制定順序が8401−3003なら、
・BASICで計算する場合に限り3003が有効で他の場合は8401が有効。
規格制定順序が3003−8401なら、
・3003に規格は8401制定に伴い自動的に無効となり、8401が優先される。
 (塩野七生『ローマ人の物語』によると、古代ローマの法体系は
  これと同じ(=後からできた法律が優先し、それと矛盾する旧法は自動的に無効になる)
  なんだそうです。 だから、ローマ法に倣って解釈すれば矛盾はあらかた押さえ込める。)


あと、JIS Z8401タイプAですが、私はこんなのを使っています。

FUNCTION R55(x,keta,eps)
! 五捨五入(数値の丸め JIS Z8401タイプA)
! x :対象数値
! kata:丸め桁。(小数keta位を丸める。)
! eps :0.5±epsの範囲は0.5とみなす。
LET bairitu=10^keta
LET fugo=sgn(x)
LET xx=abs(x)*bairitu
LET ffp=fp(xx)
IF abs(ffp-0.5)>eps THEN
LET R55=INT(xx+0.5)/bairitu*fugo ! 四捨五入
ELSE
LET R55=(INT(xx)+INT(MOD(xx,2)))/bairitu*fugo ! 五捨五入
END IF
END FUNCTION

要するに、引数が1個多いです。
何故かというと、計算誤差を吸収するため。
たとえば、
解析的に解けば、x=2.5となる事象があったとして、
数値計算で解けば、丸め誤差、桁落ち、打ちきり誤差などの影響でx=2.4999999...
となることは頻繁にあります。
こういう場合、
xを小数1位に丸めた答を、x=2.4 として良いのか、という実務上の問題があり、
「数値計算は解析的に解くかわりに近似計算している」という立場からは、
・なるべく解析的に解くのと同じ結果を与える方向にプログラミングするのが正しい
ということになるため。
※理屈はとにかく、汎用機の実数型(基数=16の浮動小数点方式)の場合、こうやらないと
 五捨五入はマトモに動作しなかったですね。

    ├FullBASICのROUND関数は 白石 和夫 2005/08/26 22:13:14  ツリーへ

Re: >PRINTUSINGは,ROUND(x,n)を適用して丸め... 返事を書く
白石 和夫 2005/08/26 22:13:14
Full BASICのROUND関数は
ROUND(x,n)=INT(x*10^n+.5)/10^n
で定義された組込み関数なので,JIS Z8401の丸めに合わなくても矛盾は生じません。
仮にZ8401-1999の記述がX 3003に及ぶと解釈しても(この解釈には賛同しませんが,)Full BASICのROUND関数がJISの丸めを行う関数ではなくなるだけのことです。ROUND関数はZ8401の丸めを行う関数として定義されているわけではないので。

    └誤解があるようなので,補足。 白石 和夫 2005/08/26 23:11:12  ツリーへ

Re: >PRINTUSINGは,ROUND(x,n)を適用して丸め... 返事を書く
白石 和夫 2005/08/26 23:11:12
誤解があるようなので,補足。
ROUND関数は,INT,TRUNCATE,CEIL,IP,FPなどと同列の数値組込み関数のひとつにすぎず,BASICにおける数値の丸め方を示すものではありません。


インデックスへ EXIT
新規発言を反映させるにはブラウザの更新ボタンを押してください。