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

タイトル Re: EXCEL 計算結果が指数表記になる。
投稿日: 2021/04/14(Wed) 22:14
投稿者魔界の仮面弁士
> 計算結果が指数表記のようなってしまっています。

小数を含む演算時には、常に【データ型】を意識するようにしましょう。

テキストボックスの値は「文字列」であって「数値」ではないので、
計算前に、明示的にデータ型を合わせる必要があるはずですよね。


'文字列連結として扱われ、文字列型の "-1.091" になる。
Debug.Print "-1.09" + "1"

'十進型同士の加算として扱われ、十進型の「-0.09」 になる。
Debug.Print CDec("-1.09") + CDec("1")

'通貨型同士の加算として扱われ、通貨型の「-0.09」 になる。
Debug.Print CCur("-1.09") + CCur("1")

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

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


> Val(テキストボックス1)+Val(テキストボックス2)としていて
MsgBox TypeName( Val("-1.09") )
を実行すると分かるかと思いますが、Val 関数の結果は 倍精度浮動小数型 です。

そして Single や Double は、二進小数で管理されるデータ型です。
そのため、0.50 や 0.75 といった値であれば誤差なく表せますが、
0.01 や 0.09 といった値は、どうしても誤差を含んでしまいます。


1÷3 という値は、三進小数であれば正確に表現できますが、
十進小数では 0.3333333333333…という循環小数になり、有限の桁数では誤差を生じます。

それと同様、1÷10 という値は、十進小数であれば正確に表現できますが、
二進小数では 0.000110011001100110011… という循環小数になってしまうのです。


無限の桁数を用意するわけにはいかないので、有効桁数を超えた分は
途中の桁で打ち切られます。それが微細な誤差として現れている理由です。


ちなみに十進型(Decimal)は、文字通り十進数でデータを保持するため、
この手の誤差が生じません。(その分、メモリ消費量や処理速度の点で劣ります)

そして通貨型(Currency)は、小数部は 4 桁固定という制限があるものの、
内部的には 64bit 整数型であるため、やはり小数部の誤差が出ません。

まぁ、Decimal や Currency が誤差が出ないとは言っても、
もちろん、1÷3 に対する打ち切り誤差などはあるのですけれどね。



なお、演算式によってもデータ型が変化することがあります。

' ほとんどの割り算は、Double 型として演算されます
Debug.Print TypeName( CLng("1") / CLng("1") )
Debug.Print TypeName( CInt("1") / CInt("1") )

' Deciaml 型同士の割り算は、Decimal 型となります
' Currency 型同士の割り算は、Currency 型となります
' Single 型同士の割り算は、Single 型となります
Debug.Print TypeName( CDec("1") / CDec("1") )
Debug.Print TypeName( CCur("1") / CCur("1") )
Debug.Print TypeName( CSng("1") / CSng("1") )

' \ 演算子による除算は、VBA では整数型になります (VB.NET の場合には、整数以外にもなりえます)
Debug.Print TypeName( CByte("1") \ CByte("1") )
Debug.Print TypeName( CInt("1") \ CInt("1") )
Debug.Print TypeName( CLng("1") \ CLng("1") )
Debug.Print TypeName( CLngLng("1") \ CLngLng("1") )


' Int 関数や Fix 関数は整数値を返しますが、データ型までは変化しないので気を付けましょう
Debug.Print TypeName( Fix(CSng("2.5")) )
Debug.Print TypeName( Fix(CDbl("2.5")) )
Debug.Print TypeName( Fix(CCur("2.5")) )
Debug.Print TypeName( Fix(CDec("2.5")) )
Debug.Print TypeName( Int(CSng("2.5")) )
Debug.Print TypeName( Int(CDbl("2.5")) )
Debug.Print TypeName( Int(CCur("2.5")) )
Debug.Print TypeName( Int(CDec("2.5")) )


' Val 関数は、渡す文字列によっては実行時エラーになる可能性があるため、
' Val といえども、変換前に文字列の内容を精査しておくことが望ましいです。
' (あるいは変換時のエラーに対処できるよう、On Error を併用するようにします)
Debug.Print Val("12.345d3&21") ' 12345
Debug.Print Val("12.3456d3&21") '変換エラー
Debug.Print Val("1.5%") '変換エラー

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

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