tagCANDY CGI VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板
VBレスキュー(花ちゃん)の Visual Basic 6.0用 掲示板
[ツリー表示へ]  [ワード検索]  [Home]

タイトル Re^2: EXCEL 計算結果が指数表記になる。
投稿日: 2021/04/15(Thu) 09:34
投稿者魔界の仮面弁士
先に述べた通り、指数表記を避けたければ、CDec 関数をお奨めしますが、
普段使うのは Double 型の方でしょうから、もう少し補足説明を。

Single や Double といった「浮動小数点数」を扱う以上は、
【有効桁数】を超える部分は誤差の範疇として、
運用上には誤差部分を無視して扱う事が求められます。

それぞれのデータ型の精度について調べておくことをお奨めします。


>> テキストボックス3に計算結果が「-9.0000000001E-2」という
>> 表記(0の個数があっていないかもしれませんが)
>
> '倍精度浮動小数型同士の加算として扱われ、倍精度浮動小数型の「-9.00000000000001E-02」 になる。
> Debug.Print CDbl("-1.09") + CDbl("1")

この時、E の前に数字が 15 個ありますよね。
これは Double 型の有効桁数が 1+52bit であることに起因しています。

最大桁が 53 bit の二進数というのは、十進数に換算すると 53×Log10(2)≒15.95458977 桁相当です。



> '単精度浮動小数型同士の加算として扱われ、単精度浮動小数型の「-9.000003E-02」 になる。
> Debug.Print CSng("-1.09") + CSng("1")

この時、E の前に数字が 7 個ありますね。
これは Single 型の有効桁数が 1+23bit であることに起因しています。

Single の有効桁数は、十進数でいうと 24×Log10(2)≒7.2247198959 相当です。


さて今回「-9.00000000000001E-02」と表示されてしまった Double 値ですが、
この内部表現である二進小数値を、そのまま十進小数に変換した場合には
 -0.0900000000000000799360577730112709105014801025390625
という値になります。

一方、CDbl("-9.00000000000001E-02") という値を求めてみると、こちらは
 -0.09000000000000009381384558082572766579687595367431640625
という、また別の値となります。僅かな差ですけれどね。


先に述べた通り、Double 型の有効桁数は 16 桁弱しかありませんので、
後半の細かい数値部には、さほど意味などありません。

これらはいずれもデバッガ上では近似値表現となり、
違いに気が付きにくいかと思いますが、参考までに
手元の環境で実験した結果を貼っておきますね。

Dim af2 As Double: af2 = CDbl("-0.09000000000000006605826996519681415520608425140380859375") ' af1 の次に大きな値
Dim af1 As Double: af1 = CDbl("-0.09000000000000007993605777301127091050148010253906250000") ' dbl の次に大きな値
Dim dbl As Double: dbl = CDbl("-0.09000000000000009381384558082572766579687595367431640625") ' = -9.00000000000001E-02
Dim bf1 As Double: bf1 = CDbl("-0.09000000000000010769163338864018442109227180480957031250") ' dbl の次に小さな値
Dim bf2 As Double: bf2 = CDbl("-0.09000000000000012156942119645464117638766765594482421875") ' bf1 の次に小さな値

' デバッガ上では、有効桁数の範囲で近似値表現されます。
Debug.Print af2  ' VBA では「-9.00000000000001E-02」表記、.NET では「-0.090000000000000066」表記
Debug.Print af1  ' VBA では「-9.00000000000001E-02」表記、.NET では「-0.09000000000000008」表記
Debug.Print dbl  ' VBA では「-9.00000000000001E-02」表記、.NET では「-0.0900000000000001」表記
Debug.Print bf1  ' VBA では「-9.00000000000001E-02」表記、.NET では「-0.090000000000000108」表記
Debug.Print bf2  ' VBA では「-9.00000000000001E-02」表記、.NET では「-0.090000000000000122」表記

' VBA 上では「-9.00000000000001E-02」という同一表記に見えますが、
' それでも内部的には別の値であり、大小関係も維持されています。
Debug.Print (af2 = af1), (af2 > af1), (af2 - af1)
Debug.Print (af1 = dbl), (af1 > dbl), (af1 - dbl)
Debug.Print (dbl = bf1), (dbl > bf1), (dbl - bf1)
Debug.Print (bf1 = bf2), (bf1 > bf2), (bf1 - bf2)



さらに言えば、CDbl("-0.09") という値の内部値は
 -0.0899999999999999966693309261245303787291049957275390625
にあたります。こちらも前後値を載せておきます。

2 つ後: -0.08999999999999996891375531049561686813831329345703125000
1 つ後: -0.08999999999999998279154311831007362343370914459228515625
元の値: -0.08999999999999999666933092612453037872910499572753906250
1 つ前: -0.09000000000000001054711873393898713402450084686279296875
2 つ前: -0.09000000000000002442490654175344388931989669799804687500


Integer 型では、1.5 という値を表現できずに 1 または 2 に丸められるのと同様、
Double 型で 0.09 という値を表現しようとした場合、格納可能な精度で丸められてしまい、
表現可能な範囲の中で最も近い値(すなわち近似値)として扱われることになります。


有効桁数を引き上げたいのであれば、CDec 関数を使ってみてください。
Decimal の有効桁数は 96bit (十進数換算で 28.89887958 桁相当)あるので、
Double 型の 15.95458977 桁よりも誤差を減らすことができます。


もちろん CDec(Val(TextBox1.Value)) などとするのは駄目ですよ。

- 関連一覧ツリー をクリックするとツリー全体を一括表示します)

古いスレッドにレスはつけられません。