★独学者が1年後にExcelVBAを爆発的に伸ばすための最低限の基礎知識メモ(ダイジェスト):Vol0015:★★★ Access2000VBA・Excel2000VBA独学~初心者の方や独学者の方へ:「パソコンは普通に小数計算をミスする」ということの重要性。そしてそんな大事なことを「最初に」教えてもらえない事(ひどさ)の重要性。~
  
バックナンバー目次ページは→こちらです。

まぐまぐのページは以下です。
https://www.mag2.com/m/0001691660.html
  
  
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
■独学者が1年後にExcelVBAを爆発的に上達させるための最低限の基礎知識メモ(ダイジェスト)

Vol.0015

タイトル:★★★ Access2000VBA・Excel2000VBA独学~初心者の方や独学者の方へ:「パソコンは普通に小数計算をミスする」ということの重要性。そしてそんな大事なことを「最初に」教えてもらえない事(ひどさ)の重要性。~
  
  

バックナンバー目次とサンプル号
https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/mag2-01

━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━━
  
  
昔、自分のブログのWebページに、Excelの小数の計算ミスやVariant型変数のデメリットのことを書きました。

今回は、それをご紹介したいと思います。

以下です。

https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/vba-kyouiku02-fool_n_big-fault

「恐ろしいこと」が分かると思います。
是非一度、お読みになってみてください。
  
  
特に、このページのイミディエイト出力での、
  

1回目のループの合計値・答え:0.1
2回目のループの合計値・答え:0.2
3回目のループの合計値・答え:0.3
4回目のループの合計値・答え:0.4
5回目のループの合計値・答え:0.5
6回目のループの合計値・答え:0.6
7回目のループの合計値・答え:0.7
8回目のループの合計値・答え:0.8000001
9回目のループの合計値・答え:0.9000001
10回目のループの合計値・答え:1

  
という部分は絶対に読んでみてください。
  

「10回目のループの合計値・答え:1」

が出る、

「10回目のループの合計値 で、あろうことか、足し算の誤差が消えてしまう」

というところが超、恐ろしいです。

  
  

小数が出てくること自体がおかしいのに、

さらに、

いったん小数が出てしまって以降は、計算ミスしつづけないとおかしいのに、

しかし、

「途中で正しい計算に戻ってしまっている」

からです。
  

つまりそれは、

「バグを見つけにくい」、

ということを意味しているからです。

  
  

「こういうことが起こる」。

「でもパソコンやExcelでは」、

「これが」、

「正常」、

なんだ、

ということです。

  
  

実は(ビックリなんですけど)、コンピュータもExcelも、小数に限っては、「計算ミスするほうが正常」なのです。
  

でもそれを「最初に」「最重要な」「注意事項!!!」として教えてくれるVBA本(もちろん一般操作の本も)は、僕は出会ったことがありません。
  

ということは、「ExcelVBA講師も言ってないことがほとんど」、と推測されます。

  
  

しかし・・・・、

Excelは「表計算」のソフトです。
  
  

「計算」。

ですよ?
  

「計算」。

なんです。
  

そんな態度が許されるでしょうか?

  
  

Youtubeなどで、このことに言及しているビデオ講師さんがどれほど居るか、一度確認してみて下さい。

僕はめんどくさいのでしませんけど・・・。
(もし誰もやってなかったら本当に面倒くさいので・・・。)

  
  

いずれにしましても、僕は実際に服屋をやっていたとき、POSレジを作っていた時、(そのときはAccessでしたが)、
「こんな簡単な小数計算もできないのかAccessは・・・」
と驚いたことがあります。

その時は、Accessの本に「基本的な小数計算は「Single型でよい」と書いてあったのでそうしたのですが、バーゲンの時に、モトの値段に0.7を掛けただけや、0.3を掛けただけ・・・、つまり、7割引や3割引きの値段を出そうとしただけだったのですが、出るはずのない小数の値が出てしまいました。

33000×0.7=23099.9996066093
2900×0.3=870.0001

という感じです。

どんな時に四捨五入したり切り捨てしたりしないといけないかが読めないため、また、自分自身、AccessVBAの初心者のようなものだったので、すぐには解決策が見つかりませんでした。

少し調べるうちに、「SingelじゃなくてDoubleやCurrencyを使え」みたいなサイトがあったので、それを見て、Currency型を使ったら治りました。

これはAccessの場合でしたが、Excelで試しても同じでした。
  

のちに、それは、
「コンピュータって、そういうもんだから。小数計算なんてミスってあたりまえっしょ!?」
という事実が判明し、さらに驚きました。
(そら昔、「Windowsを飛行機に載せようとして必死にみんなが止めた」という話もうなづけます。Macでも当然、同じでしょう。)
  

そして、今でも、小数計算を「Single型でよい」と記述する本やサイトがあります。
例えば以下のような・・・。
(↓ここはいくらなんでも「単に注意書きしてないだけ」だと思いますが‥。)
http://officetanaka.net/excel/vba/variable/03.htm

「ExcelVBA 小数計算 Single型」でGoogle検索したら、トップに出てきてしまいました・・・・。

このページの「10÷4は2.5です。しかし、変数tmpには2しか入っていません」と書いていある部分のあたりです。

もちろん、ここは、「最後の」「計算によって返された答え」だけにSingle型を使っています。
なので、このサンプルプログラムもそれに対する説明もまったく間違っていません。、

  

が、初心者の方はこれを読むと多分・・・

「小数はどんなタイプ・どんなTPOでも、全部、Single型でいいんだ」と誤解してしまいます。

こういう書き方の本がとても多いです。

あるいは、「Single型、Double型、どっちでもいい」、みたいなのとか。

なので、せめて、「答え以外に(つまり引数的な数値)には、Single型は使うな。あるいは、何が起こるかわからないから絶対に使うな。」と書いておいてほしいです。
  

ちなみに、この部分のプログラム例で、

Sub Sample2()
 Dim tmp As Single
 tmp = 10 / 4
 MsgBox tmp
End Sub

の、

tmp = 10 / 4

の行を、

tmp = 2900 * 0.3

に書き換えると、

「870.0001」という答えにはならず、
「870」と、ちゃんと正しく計算されます。

ウォッチ式(ウォッチウィンドウ)で確認すると、
掛ける数字を直書きした場合は、小数「0.3」は、「Double型」に自動認識されるようです。

  

こういうことが起こるので、
まだ初心者の段階だと(ローカルウィンドウも何も扱えない段階だと)、

こういったサンプルを見て、

「なんで小数計算にSingle型使ったらいかん?計算あってるやん!」と

「カンペキな誤解をしがち」で、

また、

「決めつけてしまいがち」

です。
  

でも、そのまま、「間違った理解のまま」
決めつけて・思い込んで、進んでしまえば、
結局はどこかの時点で「トラブる」ことになります。

なので、注意が必要です。

  

先の、Accessの
2900×0.3=870.0001
となってしまう不具合も、
「0.3」を「Single型」ではなくて「Double型」の変数に代入すると正しく計算されます。

(ただし、2900のほうを誤って「Double型」で変数宣言すると、また「とんでもない答え」が返ってきます。ご注意ください。2900のほうも、どんな型がいいのか、ご自分でループコードでも作ってお確かめください。)

  
  

・・・・というわけで、

僕はVBA内での小数計算には、「Single型は死んでも使わない」と決めています。

基本、信用してはいませんが、でも、まあ、とりあえず一応、「Double型」でやっています。
あるいは、「Double型」でやってもダメなときは、「Currency型」を使うとか・・・
  

↓以下、ご参考Webページです。
↓ExcelやExcelVBAを「表計算」のソフトという位置づけで使うなら、
↓「VBA始める前にであっても」、何よりも先に、絶対に読んでおいたほうがいいです。

https://excel-ubara.com/excelvba4/EXCEL_VBA_427.html

  
  

なお、セル同士の小数の掛け算の場合はこのような不具合が出ないことのほうが多いですが、でも、「出にくい」「少ない」ってだけで「絶対にミスしない」ってわけではなさそうなので、冒頭にご紹介したサイトを読むと、セルやVariant型の変数であっても「Excelやパソコンのバカさ」を「ナメたらあかん~」「ナメたらあかん~」ということが分かると思うので、ナメないようにしています。

  

ExcelVBAを初心者の方にお教えするうえで、この
「Excelやパソコンが、どれだけバカで、小数計算ができないか?」
「信用ならない不良品か?」
ということをスルーする講師は信用できません。
(※パソコンから見れば、人間の方が「バカ」なのかもしれませんが・・・。)

  

Excelは、計算、する、ソフトなので・・・。

  
  

以前にこのメルマガで、「ダメ講師を30秒で判断する」、という号を出しましたが、そこに、
「小数計算ミスを最初に教えない講師」
「カリキュラムに入っていない講師」
というのも、入れてもいいかもしれません。

ヘタすると、オブジェクトのこと教えない講師よりも最悪かも・・・

Excelは、計算、する、ソフトなので・・・。

  

まあ、そんなことはどうでもいいのですが、
「パソコンが計算ミスなんてするはずない」と「誤って」信じ込んでしまい、
結局プログラムを書いて「パソコンは小数計算もできないバカ」ということに気づかずにエラーが出て、
何日もWebを彷徨う実害をこうむってしまうのは、ほかでもない、皆さん自身ですので、
それを回避するために、今回の号を書かせていただきました。
(※パソコンから見れば、人間の方が「バカ」なのかもしれませんが・・・。)

  
  

是非、ご自分でも、VBEでローカルウィンドウやイミディエイトウィンドウで色々と試し、確認してほしいと思います。

例えば、バーゲンで「3割引き」の値段を出したい・・・というような時、
以下のプログラムを標準モジュールにコピペして、
「F8キーを」「★ 押し続けて ★」で、ステップ実行してみて下さい。

しばらくはいいのですが、
モトの値段が「32800円」あたりから、おかしなことになってきます。

小数計算に「Single型」を使うと「すぐに」「恐ろしいことになるんだ」、と分かると思います。

なお、このプログラムの

 Dim aa As Variant
 Dim bb As Single

の部分も、
「Double型」に変えたり、「Currency型」に変えたり、色々と試してみてください。

とくに、
「Dim aa As Variant」を
「Dim aa As Double」変えて、
「bb」はSingle型のままにしておくと、面白いことが起こります。
  

そのほか、変数の宣言は変えずに、

 aa = 1000
 bb = 0.7

の、数値を変えてみてもいいと思います。

例えば、「0.7」を「0.3」に変えると、笑えます。

  
  

ちなみに、Variant型の変数に、小数の値を代入すると、「自動的に・勝手に」、
「Double型」に内部変換されます。

「Currency型」などには自動変換されません。

なので、
https://excel-ubara.com/excelvba4/EXCEL_VBA_427.html
によりますと、「状況次第で計算ミスが起こる可能性はある」ということになります。

ご注意ください。

  

「変数なんか全部Variant型でいい」ということの「ダメさ加減」が、ここでもおわかりになるのではないかと思います。
  
  
  
  
  
==============================
  

今回は以上です。

==========================================================================

バックナンバー目次とサンプル号
  
https://euc-access-excel-db.com/tips/ct07_se/ct075012_xls2k_vba_tips/mag2-01
  
  

----------------------------------------------------------------------
■独学者が1年後にExcelVBAを爆発的に上達させるための最低限の基礎知識メモ(ダイジェスト)
発行システム:『まぐまぐ!』 http://www.mag2.com/
配信中止はこちら https://www.mag2.com/m/0001691660.html
----------------------------------------------------------------------