タイトル : 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%") '変換エラー |