LoginSignup
6
1

More than 1 year has passed since last update.

【VBS】浮動小数点の剰余

Last updated at Posted at 2021-12-05

はじめに

これは、Visual Basic Advent Calendar 2021の6日目の記事となります。

先月ネタ探しに、Yahooリアルタイム検索でVisual Basic関連で検索していた時に、下記のサイトを見つけました。

現象

If ((3091470 - 714643) * 0.2 * 62) mod 365 = 0 Then
    Call MsgBox("割り切れる")
Else
    Call MsgBox("割り切れない")
End If

上記のプログラム “sample-mod-bug1.vbs” を Windows PC に保存して実行すると「割り切れる」とメッセージが表示されます。

実際に… ((3091470 – 714643) * 0.2 * 62) ÷ 365 を計算すると、答えは 807,469.995 になります。従って、剰余は 0 ではないので「割り切れない」と表示されるべきです、、

原因

これは不具合ではなく、Classic Visual Basic系(VBScript、VBA、Visual Basic 6.0)では整数に対する剰余しか対応していないという仕様でした。その為、VB.NETではこの不具合は発生しません。

解説
剰余演算子は、number1 を number2 で割って (浮動小数点数は整数に四捨五入されます)、その余りのみを result として返します。
A = 19 Mod 6.7 ' Returns 5.
MyResult = 12.6 Mod 5 ' Returns 3.
https://docs.microsoft.com/ja-jp/office/vba/language/reference/user-interface-help/mod-operator
https://docs.microsoft.com/en-us/previous-versions/visualstudio/visual-basic-6/aa242823(v=vs.60)?redirectedfrom=MSDN

((3091470 – 714643) * 0.2 * 62) = 29472654.8 は整数に四捨五入され 29472655 となります。
29472655だと365で割り切れるため剰余も0となり、「割り切れる」というメッセージとなります。

29472655 Mod 365 = 0
29472655 / 365 = 807470

余談

ちなみにC言語では整数に対する剰余は%演算子で求められ、浮動小数点を指定するとコンパイルエラーになります。
浮動小数点数に対してはfmod関数を使用する必要があります。

.NET系では、Visual BasicはMod演算子(C#は % 演算子)では、浮動小数点数の剰余に対応しています。

サポートされている型
すべての数値型。 これには、符号なしおよび浮動小数点の型と Decimal が含まれます。
https://docs.microsoft.com/ja-jp/dotnet/visual-basic/language-reference/operators/mod-operator

対応

Mod 演算子は使用しないでfmod関数を作成する。

If fmod((3091470 - 714643) * 0.2 * 62, 365) = 0 Then
    Call MsgBox("割り切れる")
Else
    Call MsgBox("割り切れない")
End If

Function fmod(a,b)
    fmod = a - b * Int(a / b)
End Function

VBAのMod演算子とExcelのサポートしているMod数式の計算結果は異なる。
参照:剰余の計算でMod演算子とMod数式の結果が違う - Excel VBAコーディング ガイドライン案

最後に

以前、端数処理でExcelで計算した結果と違うので不具合ではないかとユーザーから確認があったことを思い出しました。ユーザーはExcelを使用していることが多いので、Excelの数式とプログラム言語での結果が違うというのは困り物ですね。

6
1
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
6
1