プロが教える店舗&オフィスのセキュリティ対策術

タイトルどおりなのですが
VBAでのコーディングを教えてください。
余りを求めてそれを判定に使いたいのですが・・

あと偶数か奇数かの判定の記述があれば
それもお教え下さい。

A 回答 (5件)

こんにちは、KenKen_SP です。



>VBAでの割り算の余りの求め方

通常は Mod 演算子を使います。ただし、この時に返される剰余が
浮動小数である場合には整数に丸められます。例が悪いかもしれ
ませんが、

Dim a As Currency
a = 19 Mod 6.7

だと 整数 5 に丸められて返されます。実際に計算すると 5.6
ですね。

PC でこのような浮動少数を扱う以上は丸め誤差はつきものですが、
これでは困る場合は、自分で関数を作ってやります。

下記コードを標準モジュールにコピー&ペーストし、結果を比較
してみて下さい。

Sub Sample()
  
  Dim a As Currency
  Dim b As Currency
  Dim c As Currency

  a = 19
  b = 6.7
  c = a Mod b
  MsgBox "MOD演算子による剰余:" & CStr(c)

  c = MOD2(a, b)
  MsgBox "自作MOD2関数による剰余:" & CStr(c)

End Sub

'// 剰余を求める関数
Function MOD2( _
  ByVal Num1 As Currency, _
  ByVal Num2 As Currency) As Currency

  MOD2 = Num1 - Int(Num1 / Num2) * Num2

End Function

>偶数か奇数かの判定の記述

まずは偶数・奇数の数学的な定義です。

【偶数】2で割り切れる自然数
【奇数】2で割り切れな自然数

つまり判定値が 0 や -1 や 15.6 などの場合は

「どちらでもない」

となります。この点はどのようにお考えですか?
これにより記述方法が変わります。
    • good
    • 0
この回答へのお礼

ありがとうございます。
サンプル参考になりました。

お礼日時:2006/02/18 08:43

KenKen_SPさん、こんにちは。



私が考えたのは、Mod の戻り値のデータ型のことです。元々、Double型を含む、それ以上の高精度のデータ型の戻り値の変数に使っても、低精度にキャストしてしまう演算子では、そのようにしても無駄になってしまうと考えました。

VBAのMod演算子は、戻り値のデータ型が整数の低精度にキャストされてしまうのですから、求める解の精度で、Double型以上の高い精度を求めるなら、Mod は当然使えないわけですね。

確かに、データの「丸め」は発生していますが、それは誤差ではなくて、むしろデータ型自体がキャストされているのだと考えて良いかと思います。それは、単なる結果論なのかもしれませんが、どのようにしても、ModではLong型以上の精度を上げることが出来ません。私の#3のコードは、Mod を使って、その戻り値が、Long型であろうが、Double型であろうが、それは、Long型以内に統一させられるということを示したに過ぎません。

戻り値の型をCurrency 型を使っても、Long型を使っても、Mod演算子を使った場合、異なる結果は発生しないだろうと思います。
    • good
    • 0

んーー書き方が悪かったみたいですね、、



Mod 演算子の内部計算で丸め誤差が発生する、、というところを問題
にしているわけではありません。

PC で少数を扱う場合は結果において「丸め誤差」が発生する可能性は
つきものです。それは内部演算の過程で発生もする場合もあるし、それ
が仕様であったりします。

ここで Mod 演算子は「仕様」で戻り値が丸められて返されます。

剰余を求めるのに Mod 演算子を使ってはいけない、Mod 演算子は間違っ
た値を返すから、、と別に言っているわけではないですよ。

Dim a As Currency
a = 19 Mod 6.7

で5が帰るのは仕様どおりで、エラーではありませんし、この結果の
方が多くの場合は使われるでしょう。

ただ、ユーザーが剰余を少数まで期待する場合、丸められた5という
戻り値はユーザーにとってはやっぱり「丸め誤差」があるのです。

その場合は自前で計算しましょう、、というのが意図するところです。

あと、コードを拝見しましたが変数の型は Currency 型の方がいいと
思います。

んーー。。すみません。Wendy02 さんの言わんとしているところを理解
できません。
    • good
    • 0

こんにちは。


Wendy02です。

ご質問者さんのスレッドに、割り込ませていただきます。直接、ご質問から離れてしまいますので、申し訳ありません。

KenKen_SP さん へ

>Dim a As Currency
>a = 19 Mod 6.7

>整数 5 に丸められて返されます。実際に計算すると 5.6

私は、以前、時間計算の時に、他の方からご指摘いただいたのですが、Mod の戻り値は、整数型で、ワークシート関数のMod のように、Double型ではありません。

これは、浮動小数点数の丸め誤差ではなくて、Mod 演算子の戻り値が、単に下位の整数のデータ型、言い方を換えれば、Double型以上では表現できないからだと思います。

言い方を換えると、そこに浮動小数点丸め誤差が発生しているかは、整数型では分らないのです。浮動小数点丸め誤差は、その演算の過程で起こるものであって、その結果に発生するわけではないからなのです。

Sub FloatingDecimalDifference()
Dim Dividend As Double
Dim Divisor As Double
Dim dblResult1 As Double
Dim dblResult2 As Double
Dim lngResult3 As Long
Dim Result1
Dim Result2

Dividend = 1.13 * 100 '被除数 または、1.13
Divisor = 0.52 * 100 '除数  または、0.52

'この演算過程で、浮動小数点誤差が発生しています。
dblResult1 = Dividend - Int(Dividend / Divisor) * Divisor

'修正しました。
dblResult2 = CDec(Dividend) - CDec(Int(Dividend / Divisor) * Divisor)

'Long型では、丸められています。
lngResult3 = Dividend - Int(Dividend / Divisor) * Divisor

'しかし、ここでは、dblResult2 とlngResult3の結果の区別はありません。

Result1 = Dividend \ Divisor
Result2 = Dividend Mod Divisor

Stop

End Sub

ここでは、dblResult2 とlngResult3の区別はありません。また、lngResult3 とResult2 の区別も付きません。
つまり、Result2 が、Variant 型で、 Mod の引数が、Double 型でも、Result2 は、Long型にキャストされているからです。

ワークシートでは、

A1:
=MOD(1.13,0.52)
は、
0.09 と出ますが、
= A1=0.09
とすれば、False になります。

これは、ワークシートは、Double型しかありませんし、Mod自体も、そのままの桁を戻り値としますから、その内部で、浮動小数点丸め誤差が出ていることが分りますが、VBAは、整数型に丸められているので、それは Double型を含む、それ以上には、それらの演算子の戻り値が返されませんから、誤差が発生しているのか分らないと思うのです。

また、もしも、奇数・偶数かを判定するのでしたら、ワークシートのISEVEN などの関数に準拠させるのが最も楽な方法だとも思えます。

# 数値 評価する数値を指定します。数値 に整数以外の値を指定すると、小数点以下が切り捨てられます

以下は、Excelならではですが、現実には、VBAでは使われないとは思いますが、ワークシートの少数点固定法で以下のような方法もあってもよいかもしれません。
c.f.

a = 1.13
b = 0.52

c3 = CDbl(Evaluate("Fixed(Mod(" & a & ", " & b & "),2)"))

最後の丸めの少数桁は、仮に 15 でも同じです。

なお、VBAでは、このようなことはしませんが、参照設定すれば以下のように出来ないこともありません。(設定: atpusrc1.xls =分析ツール) 
iseven(10.56) 
たぶん、仕様の参考にはなるような気がします。
    • good
    • 0

余りはMod演算子を使用します。

また、数字を2で割れば奇数は1で偶数は0になるので判定ができます。

あとは自分で調べれば、容易にできるでしょう。
    • good
    • 0
この回答へのお礼

ありがとうございます!

お礼日時:2006/02/18 08:45

お探しのQ&Aが見つからない時は、教えて!gooで質問しましょう!