こんにちはゲストさん。会員登録(無料)して質問・回答してみよう!

解決済みの質問

エクセルVBAとワークシート関数が違う答え?

エクセル2013です。
A1セルからA100セルにすべて1%と入力されています。
BIセルに
=SUM(A:A)
と数式が入っており、100%と表示されています。
A,B列のセルの書式はすべてパーセテージです。
101行以下には何も入っていません。

C1セルに
=B1=1
と数式が入っており、TRUEが表示されています。

標準モジュールに
Sub test01()
MsgBox Range("B1").Value = 1
End Sub
と書きました。
実行したところFalseが帰ってきました。
なぜ、TRUEにならないのでしょうか?
なお、
Sub test02()
MsgBox Val(Range("B1").Value) = 1
End Sub
とすると、TRUEが帰ります。
でも、Val関数はStringを数値化するものですよね?
B1セルはもともと数値なのでVal関数で答えが変わるのも不思議です。

どなたか、わかるように教えていただけないでしょうか?

投稿日時 - 2013-12-25 18:54:41

QNo.8400543

困ってます

質問者が選んだベストアンサー

本当に正確・詳細な仕様(内部計算)のこととなると、Microsoft の社員でなければ説明できないかもしれませんが、分かっていることについて書きます。

Excel では、小数の計算をするとき、誤差がある程度小さい場合に、自動的にそれを除去するという機能があります。申し訳ないですが、詳しい発動条件は説明できません。それらしいケースがあるのは確かだと分かっているだけです。

参考 URL を参考にしてください。ページ中、5 ~ 6 割くらい進んだ位置に、「実は、エクセルには自動的に……」と述べられています。できればページ全部を読んでみることをお勧めします。


>=ROUND(SUM(A:A),100) としても……が、TRUEを返すのはなぜでしょう?

先ほどの Val 関数というのは丸めることが目的の関数ではないわけですが、結果として、数値から誤差が取り除かれていました(いたようでした)。同様に ROUND も、何桁であろうとも、関数を通すだけで誤差を取り除いてしまうと考えるほかないのではないかと思います。

他のセルの Value プロパティに、SUM による誤差を含む計算結果を放り込むということをしても、誤差は消えているようです。そこから更に 1 を引いて 10^16 を掛けても、結果は 30 桁、ゼロ行進です。

一般には、このような微小な差分や関数の性質まで含めて考えるとなると、ワークシート上の数式と VBA プロシージャでの計算の双方で、同様な処理を行ったとして、両者の挙動が一致する保証、あるいは一致しない保証は、ないと思います。

誤差が発生する可能性の有無が不明な場合は、参考 URL でも言及されていることですが、適度な桁数で ROUND しておけということですね。発生し得るのは小数の場合のみですから、整数化しておけば安心です。ただし整数ではなく小数点以下に何桁か残す場合の、ROUND による計算結果も誤差を含む場合があるという問題が実はありますが。


>ますますわからなくなってきました・・・・・。

正直、キリがなくなりますんで、あまり深く考えないことをお勧めします。ご関心があるようなら、追々研究していくという方針がよろしいかと。

参考URL:http://pc.nikkeibp.co.jp/pc21/special/gosa/eg1.shtml

投稿日時 - 2013-12-26 01:42:46

お礼

ありがとうございます。
参考URL読ませていただきました。
小数点以下も扱うので、今回はB1セルの数式を =Round(SUM(A:A),8) として対応しました。

よいお年をお迎えください。

投稿日時 - 2013-12-27 23:39:37

このQ&Aは役に立ちましたか?

0人が「このQ&Aが役に立った」と投票しています

回答(2)

どこかのセルに、=(b1-1)*10^14 と記入してみてください。計算誤差が発生していることが分かります。小数を交えた計算では、こういうことが起こり得ます。

B1 セルの数式を =round(SUM(A:A),5) といった感じに丸めるように書き換えて、もう一度 MsgBox Range("B1").Value = 1 を実行してみてください。今度は True になると思います。

VBA の Val 関数が型変換の過程で、丸めてしまうのですかね。しかしワークシート関数の VALUE で SUM の戻り値を処理しても、True にはなりませんでした。

投稿日時 - 2013-12-25 20:31:46

お礼

ありがとうございます。
=(B1-1)*10^14  でエクセルの計算誤差が見えました。
0.0666133814775094
が返りました。
ただ、それならなんでワークシート上では
=B1=1
が、TRUEを返すのでしょう?
また、計算誤差部分を丸めないように
=ROUND(SUM(A:A),100)
としても
MsgBox Range("B1").Value = 1
が、TRUEを返すのはなぜでしょう?
ますますわからなくなってきました・・・・・。

投稿日時 - 2013-12-25 23:11:51

あなたにオススメの質問