浮動小数点数版(統合版)の結果表示No.01594
山紫水明 さん 07/12/16 21:16
 
秀丸担当さん,
次のようなテストマクロを実行します。
#b の 値が 0,1  1.1  2.1  3.2  の場合は問題ないのですが,4.1  5.1  9.1
の場合に表示が変です(6.1  7.1  8.1 でも同じです)。
再現しますでしょうか?

//--------------------------------------------//
setfloatmode 1;
#a = 0.1;
#b = 0.1;
message str(#a + #b);//0.2
#b = 1.1;
message str(#a + #b);//1.2
#b = 2.1;
message str(#a + #b);//2.2
#b = 3.1;
message str(#a + #b);//3.2
#b = 4.1;
message str(#a + #b);//4.199999999999999
#b = 5.1;
message str(#a + #b);//5.199999999999999
#b = 9.1;
message str(#a + #b);//9.199999999999999
endmacro;
//--------------------------------------------//

浮動小数点数版(統合版)Ver.7.07 +  Windows Vistaです。

              山紫水明

[ ]
RE:01594 浮動小数点数版(統合版)の結果表No.01595
秀丸担当 さん 07/12/17 12:33
 

>次のようなテストマクロを実行します。
>#b の 値が 0,1  1.1  2.1  3.2  の場合は問題ないのですが,4.1  5.1  9.1
>の場合に表示が変です(6.1  7.1  8.1 でも同じです)。
>再現しますでしょうか?

マクロで再現できました。
これは、以下の件でstr文の精度を上げたため、そうなってしまっているようで
す。
http://www.maruo.co.jp/hidesoft/2/x23410_.html#23410

いろいろ試してみたら1桁精度を下げると大丈夫なようで、V7.08で修正してみ
ようと思います。


詳しく書くと、str文で浮動少数点数の場合は C の sprintf を使っているので
すが、V6.14までは
  double n;
  sprintf( sz, "%lG", n );
としてありました。

これでは切り捨てが多すぎるということで、V7.00から
  double n;
  sprintf( sz, "%1.16lG", n );
としてあります。

ソース中に直接
  sprintf( sz, "%1.16lG", 4.2 );
  sprintf( sz, "%1.16lG", 4.1+0.1 );
と書くと、
上は"4.2"で、下は"4.199999999999999"でした。
どうも 4.2 と 4.1+0.1 は double の計算では微妙に違う値になるよう
で・・・?

"%1.15lG"にすると大丈夫なようなので、そのように修正しておこうかと。

[ ]
RE:01595 浮動小数点数版(統合版)の結果表No.01596
いいじま さん 07/12/17 12:55
 
秀丸担当さん、こんにちは。いいじま@横槍です。

>  sprintf( sz, "%1.16lG", 4.2 );
>  sprintf( sz, "%1.16lG", 4.1+0.1 );
> と書くと、
> 上は"4.2"で、下は"4.199999999999999"でした。
> どうも 4.2 と 4.1+0.1 は double の計算では微妙に違う値になるよう
> で・・・?

これは、小数を扱う上でどうしても避けられない問題です。
コンピュータ内部では小数も内部的には2進法なのですが、このとき、
10進法の0.1、0.2…は循環小数になります。とするとどこかで丸めないと
いけないわけで、丸めるタイミングによって、期待している値とは違う
微妙な誤差が出ます。

これはけっこう深刻な問題でして、その対策だけで本が1冊書けるほどです。

何桁かかさ上げして、たとえば4.2はマクロ内部では420として表して表示のときに
100.0で割るとか、そういう工夫が必要になってきます。

[ ]