タイトル | : Re^2: EXCEL 計算結果が指数表記になる。 |
記事No | : 16611 |
投稿日 | : 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)) などとするのは駄目ですよ。
|