新しく発言する EXIT インデックスへ
丸め誤差の報告

  丸め誤差の報告 是枝 秀明 2004/03/06 14:11:38 
  おそらくROUND(X,N)の定義がINT(x*10^n+0.5... 白川和樹 2004/03/06 15:06:02 
  ROUND(x,n)は,JISでINT(x*10^n+0.5)/10^nと... 白石和夫 2004/03/06 15:12:15 
   └私の理解不足よる勘違いでした。大変失礼し... 是枝 秀明 2004/03/07 14:21:33 

  丸め誤差の報告 是枝 秀明 2004/03/06 14:11:38  ツリーへ

丸め誤差の報告 返事を書く
是枝 秀明 2004/03/06 14:11:38
いつもBasic 32 を使用させて頂いています。
round関数で丸め誤差が発生するようですのでご報告します。

A=round(1.1*(-152.5)+0.9*102.75+0.9*80.80+1.2*0,2) の計算結果が-2.55 (正-2.56) になりました。(10進,10進1000桁)
(実際の計算は変数を代入していますが,上記の値が入力された時に丸め誤差が発生しました。)
式を分解して計算してみたら Test 1 と Test 3 で丸め誤差が発生しているようです。(2進では Test 1,2,3)



! Sample Program 丸め誤差(桁落ち) 2004/3/6 (Sat)
!
! 元式
LET A = 1.1*(-152.5) + 0.9*102.75 + 0.9*80.80 + 1.2*0
PRINT "A = " ,A,ROUND(A,2) ! -2.555 , -2.55 (-2.56 ?)

! Test 1 負を正
LET A2 = 1.1*152.5 + 0.9*102.75 + 0.9*80.80 + 1.2*0
PRINT "A2 = " ,A2,ROUND(A2,2) ! 332.945 , 332.95

! Test 2 ±逆
LET A3 = 1.1*152.5 - 0.9*102.75 - 0.9*80.80 - 1.2*0
PRINT "A3 = " ,A3,ROUND(A3,2) ! 2.555 , 2.56

! Test 3 1項目
LET B1 = 1.1*(-152.5)
PRINT "B1 = " ,B1,ROUND(B1,1) ! -167.75 , -167.7 (-167.8 ?)

! Test 4 1項目 負を正
LET B2 = 1.1*152.5
PRINT "B2 = " ,B2,ROUND(B2,1) ! 167.75 , 167.8

! Test 5 2項目
LET C = 0.9*102.75
PRINT "C = " ,C,ROUND(C,2) ! 92.475 , 92.48

! Test 6 3項目
LET D = 0.9*80.80
PRINT "D = " ,D,ROUND(D,2) ! 72.72 , 72.72

END

  おそらくROUND(X,N)の定義がINT(x*10^n+0.5... 白川和樹 2004/03/06 15:06:02  ツリーへ

Re: 丸め誤差の報告 返事を書く
白川和樹 2004/03/06 15:06:02
おそらくROUND(X,N)の定義がINT(x*10^n+0.5)/10^n(ヘルプ参照)
なので元式のようにXが-の場合
ROUND(A,2)=(-2.555*10^2+0.5)/10^2
=(-255.5+0.5)/100
=-2.55
となる訳だと思われます
対策は例えば少し行が長くなりますが
LET A = 1.1*(-152.5) + 0.9*102.75 + 0.9*80.80 + 1.2*0
LET A1=ROUND(ABS(A),2)
IF A<0 THEN LET A1=-A1
PRINT "A = " ,A,A1
のようにAを1度正の数に直して後で再び負の数にするなどです

  ROUND(x,n)は,JISでINT(x*10^n+0.5)/10^nと... 白石和夫 2004/03/06 15:12:15  ツリーへ

Re: 丸め誤差の報告 返事を書く
白石和夫 2004/03/06 15:12:15
ROUND(x,n)は,JISでINT(x*10^n+0.5)/10^nと定義されています。ですから,ROUND(x,n)と-ROUND(-x,n)とが異なる値になることがあります。
内部構造的には負数xに対してROUND(x,n)=-ROUND(-x,n)で定義したほうが簡単なのですが,ROUND(x,n)=INT(x*10^n+0.5)/10^nはJISの規定です。


   └私の理解不足よる勘違いでした。大変失礼し... 是枝 秀明 2004/03/07 14:21:33  ツリーへ

Re: ROUND(x,n)は,JISでINT(x*10^n+0.5)/10^nと... 返事を書く
是枝 秀明 2004/03/07 14:21:33
私の理解不足よる勘違いでした。大変失礼しました。
書き込む前にJIS規格を確認したのですが,round(x)=int(abs(x)*10^n+0.5)/10^n*sgn(x) と思い込んでいましたので,自分の間違いに気が付きませんでした。
昔 round関数のない処理系で INT関数で処理していたのを思い出しました。
今まで気付かずにround関数を使用していたのですが,今後気を付けて使用します。

以下の様にプログラムを修正して対処します。
! main program
DECLARE EXTERNAL FUNCTION ROUND
END

EXTERNAL FUNCTION ROUND(x,n) ! 絶対値が大きい方の値に四捨五入 (規則B)
LET ROUND = INT(ABS(x)*10^n+0.5)/10^n*SGN(x)
END FUNCTION


ついでに他の処理系での数値の丸め方を調べてみました。
 True Basic 'round' Full Basic に同じ。
Excel 'round' 絶対値が大きい方の値に四捨五入 (規則B)
Exce VBA 'round' 絶対値が大きい方の値に四捨五入 (規則A)
 Fortran   'ANINT' 絶対値の大きい方の値に四捨五入

Excelの場合Excelの組込関数とVBAの組込関数では 'JIS Z8401 数値の丸め方' の取り扱いが違うので不便です。
Delphiのround関数は規則Aだそうですね。

私の理解不足で,桁落ちによる演算誤差と思い込んでしまいました。
(JIS規格は私には抵抗があります。)
'JIS Z8401 数値の丸め方'の規則Aと規則Bの違いなど数値の丸め方は難しいですね。

ありがとうございました。


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