Excel VBA質問箱 IV

当質問箱は、有志のボランティア精神のおかげで成り立っています。
問題が解決したら、必ずお礼をしましょうね。
本サイトの基本方針をまとめました。こちら をご一読ください。

投稿種別の選択が必要です。ご注意ください。
迷惑投稿防止のため、URLの入力を制限しています。ご了承ください。


2553 / 13646 ツリー ←次へ | 前へ→

【67298】単純な計算がうまくできません。 八家九僧陀 10/11/21(日) 21:30 質問[未読]
【67299】Re:単純な計算がうまくできません。 kanabun 10/11/21(日) 21:34 発言[未読]
【67300】Re:単純な計算がうまくできません。 kanabun 10/11/22(月) 9:50 発言[未読]
【67301】Re:単純な計算がうまくできません。 kanabun 10/11/22(月) 10:15 発言[未読]
【67304】Re:単純な計算がうまくできません。 八家九僧陀 10/11/22(月) 19:18 お礼[未読]
【67303】Re:単純な計算がうまくできません。 ホグペン 10/11/22(月) 17:20 回答[未読]

【67298】単純な計算がうまくできません。
質問  八家九僧陀  - 10/11/21(日) 21:30 -

引用なし
パスワード
   「電子計算機等による年末調整」事務のVBAを作っているのですが、ごく単純な計算がうまくいきません。
ある金額(Aとします)のランクにより、そのランクの率、控除額を抽出、適用して、「A×率-控除額」(円未満切捨て)の計算をします。

金額が6,835,000円の場合、率は0.9、控除額は1,200,000円なので、「6,835,000*0.9-1,200,000」=4,951,500となるはずが、なぜか「4,951,499」と、ありえない数値になってしまい悩んでいます。

以下がそのVBAですが、その解決方法をご教示ください。

Private sub 計算()

Dim 年調給与額 As Long
年調給与額=Val(Text年調給与額.Value)'この場合[6,835,000]

Dim ritu_1 As Single '率 この場合[ 0.9 ]
Dim kouzyo_1 As Long '控除額 この場合[ 1,200,000 ]

Select Case 年調給与額

  Case 年調給与額=Range("A2").Value To Range("B2").Value
    ritu_1=Val(Range("C2").Value)
    kouzyo_1=Val(Range("D2").Value)

  Case 年調給与額=Range("A3").Value To Range("B3").Value
    ritu_1=Val(Range("C3").Value)
    kouzyo_1=Val(Range("D3").Value)

以下 9ランクほどのコードを記述しています。

Case Else
    ritu_1=0
    kouzyo_1=0

Text控除後所得額.Value = Application.WorksheetFunction.RoundDown(年調給与額 * ritu_1 - kouzyo_1,0)

なお、「MsgBox 年調給与額 * ritu_1 - kouzyo_1」でMsgBoxに表示させると、
[ 4951499.8370409 ]と ありえない??表示(計算)がされています。
そのRounddownですから、[ 4,951,499 ]となるのは分かるのですが、単純に「4,951,500」のはずが、なぜ[ 4951499.8370409 ]と計算されるのか、訳が分かりません。どなたか、その原因、解決法を教えてください。

【67299】Re:単純な計算がうまくできません。
発言  kanabun  - 10/11/21(日) 21:34 -

引用なし
パスワード
   ▼八家九僧陀 さん:
こんにちは〜

>「6,835,000*0.9-1,200,000」=4,951,500となるはずが、なぜか「4,951,499」と、ありえない数値になってしまい悩んでいます。
>
>[ 4951499.8370409 ]と ありえない??表示(計算)がされています。

全部みてませんが、

> Dim ritu_1 As Single '率 この場合[ 0.9 ]

とりあえず、これがいけない。

Dim ritu_1 As Double

としてみてください。


【67300】Re:単純な計算がうまくできません。
発言  kanabun  - 10/11/22(月) 9:50 -

引用なし
パスワード
   ▼八家九僧陀 さん:

0.9という実数値を Single型の変数に代入したばあいと、
Double型の変数に代入して計算したばあいとでは
前者では【桁落ち】が生じやすいので、
0.9 が 0.900000000000  として計算されていない
ということです。

比較検証するプロシージャをつくってみましたので、
お試しください:

'--------------------------------- 標準モジュール
Sub 端数が出る理由_Single()
 
 Dim 年調給与額 As Long
 Dim ritu_1  As Single
 
 年調給与額 = Val("6835000")
 ritu_1 = 0.9
 
 Debug.Print
 Debug.Print 年調給与額; " * "; ritu_1;
 Debug.Print " <----"; TypeName(ritu_1); CDbl(ritu_1)
 Debug.Print 年調給与額 * ritu_1
 
End Sub

Sub 端数が出る理由_Double()
 
 Dim 年調給与額 As Long
 Dim ritu_1  As Double
 
 年調給与額 = Val("6835000")
 ritu_1 = 0.9
 
 Debug.Print
 Debug.Print 年調給与額; " * "; ritu_1;
 Debug.Print " <----"; TypeName(ritu_1); CDbl(ritu_1)
 Debug.Print 年調給与額 * ritu_1
 
End Sub

'------------------------ イミディエイト・ウィンドウ
6835000 * 0.9 <----Single 0.899999976158142
6151499.8370409

6835000 * 0.9 <----Double 0.9
6151500

【67301】Re:単純な計算がうまくできません。
発言  kanabun  - 10/11/22(月) 10:15 -

引用なし
パスワード
   あと、お金の計算だから
貨幣型(Currency) というのもあります。

詳細は ヘルプの「データ型の詳細」で Currency を参照ください。

【67303】Re:単純な計算がうまくできません。
回答  ホグペン  - 10/11/22(月) 17:20 -

引用なし
パスワード
    コンピュータで小数を扱うとき、厳密には表せません。

 普通の10進法でたとえますと、1÷3 を小数で表すと 0.3333…… と無限に続きます。有限の小数で表さなくてはならないとすると、例えば 0.3333 とどこかで切らなくてはなりません。つまり近似的な値でしか扱えないわけです。
 ですから、このような制限の元で1÷3×3 という計算をすると、結果が 0.9999 と「あり得ない計算」になってしまいます。

 今回の問題は 0.9 という値を コンピュータの使っている2進数できちんと表せないところにあります。これは現在のコンピュータを使う限り避けられない問題で、「演算誤差」と呼ばれます。

 お金の関わる計算で小数を扱うときには、この演算誤差の問題を意識しておかなければなりません。

達人”芳坂和行氏に学ぶ、エクセル(Excel)「演算誤差」対策講座

というページがあり、参考になると思います。(URL を貼り付けようとしたところ、禁止語句とかではじかれてしまいました。上の言葉で検索をかければすぐ見つかると思います。)

【67304】Re:単純な計算がうまくできません。
お礼  八家九僧陀  - 10/11/22(月) 19:18 -

引用なし
パスワード
   SingleをDoubleに、LongをCurrencyに訂正して、うまくいきました。
ありがとうございます。
「Excel VBA できる大辞典」という参考書を買って勉強していましたが、「Sinngle 小数点を含む数値を保存する」「Double Singleよりも大きな桁の小数点を含む数値を保存する」「Long 整数型(Integer)では保存できないような大きな桁の整数値を保存する」「Currency 15桁の整数部分と4桁の少数部分を保存する」という解説があるのみであったので、単純に[0.9]なら大きな桁ではないから[Single]、15桁の金額を計算するわけでもないので[Long]で、とデータ型の本質?を理解せぬまま使っていました。
やっぱり質問してみて、参考書には解説のないことも教えていただくことができ、ほんとうによかったです。
これからも他の内容で、なにかとお世話になるかもわかりませんが、ご教示お願いします。
お二人方、ほんとうにありがとうございました。モヤモヤが晴れてスッとしました。

2553 / 13646 ツリー ←次へ | 前へ→
ページ:  ┃  記事番号:
2610219
(SS)C-BOARD v3.8 is Free