FC2ブログ

Excelじゆうちょう

Excelのお絵描きツール『りっぷ2(りっぷつぅ)』のサポートページ、まずは「はじめに」をご覧ください。 [NewEntry] [Admin]

記事更新カレンダー

11 « 2018-12 « 01
- - - - - - 1
2 3 4 5 6 7 8
9 10 11 12 13 14 15
16 17 18 19 20 21 22
23 24 25 26 27 28 29
30 31 - - - - -

やたらに多いカテゴリ

比較的新しい記事

新しいコメント

ありがたいブログ拍手

拍手コメント一覧(拍手はしない)

さみしいトラックバック

申し訳ないプロフィール

申し訳ない

管理人  [ 申し訳ない ]

pxivもやってます
リンクの一番上からのぞきに来てください
※閲覧にはユーザー登録が必要です

RSSってなんぞ?

広告は消せないらしい

FC2Ad

        --------       スポンサーサイト

上記の広告は1ヶ月以上更新のないブログに表示されています。
新しい記事を書く事で広告が消せます。

        2010-01-14       さらに詳しく、For … Next

12/27(日)の記事 より引用、ここから】
ちょっとしたマクロを組む時でも、繰り返し処理をする場面は多々あります。
基本的なFor … NextステートメントやDo … Loopステートメントをはじめ、再帰呼び出しやGoToステートメントなどで繰り返しをさせます。
この中でもっともお世話になるのがFor … Nextステートメントです。(少なくとも私はそう)
それだけに、VBAの入門書でも早々に紹介されています。

基本的な使い方はそちらにおまかせするとして、ここではもう少し掘り下げた内容を記事にしたいと思います。
For … Nextステートメントは、繰り返しのカウンタ値、開始値、終了値、ステップ数を指定します。
これらの値を色々と変えて、それぞれでカウンタ値がどう変化するかを調べます。
12/27(日)の記事 より引用、ここまで】

前回、testFor1で開始値、終了値、ステップ数を小数にすると、カウンタが終了値に達していないのにループが終了してしまいました。
どうしてこんな結果になるのでしょうか?
原因はExcelではありません、PCの仕様にまでさかのぼってしまいます。

PCはすべての処理を0か1だけで行っています。
もちろん、ディスプレイには2やら3などの数字もあれば、文字列や画像、スピーカからは音も鳴ります。
これは、PCが処理した0と1をそれぞれの出力に合わせて変換されているからです。

で、これがどうして結果に影響するのかというと、PCの中での0.1は正確な0.1ではないからです。
わかりにくいですね。
PCの中での数値は0と1の2進数で処理されます。
10進数の32進数の1010進数の152進数の1111といった具合です。
そして、2進数で小数を表現しようとすると、10進数の0.52進数の0.110進数の0.252進数の0.01となります。

問題はここからです。
10進数の0.12進数の0.000110011001100…、割りきれません。
つまり、誤差が生じてしまいます。
これがループで蓄積され、終了値と一致しない結果となってしまいました。

【補足】
これはtestFor8の条件の場合です、小数の値が異なれば誤差が小さくて結果に影響しない場合もあります。

以上より、2進数でも割り切れる小数を使えば問題ないはずです。

■開始値、終了値、ステップ数が小数


'【コードウインドウ】
Private Sub testFor8() '開始値、終了値、ステップ数が小数(2進数で割り切れる)
Dim For_cnt As Single, For_start As Single, For_end As Single, For_step As Single
For_start = 0.5
For_end = 1.5
For_step = 0.5

For For_cnt = For_start To For_end Step For_step
  Debug.Print "ループ中のカウンタ値 = " & For_cnt
Next For_cnt
Debug.Print "ループ後のカウンタ値 = " & For_cnt
End Sub

'【イミディエイトウインドウ】
ループ中のカウンタ値 = 0.5
ループ中のカウンタ値 = 1
ループ中のカウンタ値 = 1.5

ループ後のカウンタ値 = 2


こんなことに気を使うくらいなら、最初から小数を使わない方が無難ですけど。

【おまけ】
ステップ数について、ちょこっとだけ。
・ステップ数に0を指定すると、無限ループになる
  別途終了判定を組む必要があります、ていうかDo … Loopステートメントを使ってください。
・For Each … Nextステートメントには、ステップ数を指定できない
  対象がオブジェクトですので、数値では管理できません。
スポンサーサイト

        2009-12-29       もっと詳しく、For … Next

前回 より引用、ここから】
ちょっとしたマクロを組む時でも、繰り返し処理をする場面は多々あります。
基本的なFor … NextステートメントやDo … Loopステートメントをはじめ、再帰呼び出しやGoToステートメントなどで繰り返しをさせます。
この中でもっともお世話になるのがFor … Nextステートメントです。(少なくとも私はそう)
それだけに、VBAの入門書でも早々に紹介されています。

基本的な使い方はそちらにおまかせするとして、ここではもう少し掘り下げた内容を記事にしたいと思います。
For … Nextステートメントは、繰り返しのカウンタ値、開始値、終了値、ステップ数を指定します。
これらの値を色々と変えて、それぞれでカウンタ値がどう変化するかを調べます。
前回 より引用、ここまで】

■開始値、終了値、ステップ数をループ中に変更


'【コードウインドウ】
Private Sub testFor6() '開始値、終了値、ステップ数をループ中に変更
Dim For_cnt As Long, For_start As Long, For_end As Long, For_step As Long
For_start = 1
For_end = 5
For_step = 1

For For_cnt = For_start To For_end Step For_step
  For_start = 10
  For_end = 50
  For_step = 10

  Debug.Print "ループ中のカウンタ値 = " & For_cnt
Next For_cnt
Debug.Print "ループ後のカウンタ値 = " & For_cnt
End Sub

'【イミディエイトウインドウ】
ループ中のカウンタ値 = 1
ループ中のカウンタ値 = 2
ループ中のカウンタ値 = 3
ループ中のカウンタ値 = 4
ループ中のカウンタ値 = 5

ループ後のカウンタ値 = 6


開始値、終了値、ステップ数は最初に読み込まれ、変更はできないようです。

■カウンタ値をループ中に変更


'【コードウインドウ】
Private Sub testFor7() 'カウンタ値をループ中に変更
Dim For_cnt As Long, For_start As Long, For_end As Long, For_step As Long
For_start = 1
For_end = 5
For_step = 1

For For_cnt = For_start To For_end Step For_step
  For_cnt = 10
  Debug.Print "ループ中のカウンタ値 = " & For_cnt
Next For_cnt
Debug.Print "ループ後のカウンタ値 = " & For_cnt
End Sub

'【イミディエイトウインドウ】
ループ中のカウンタ値 = 10
ループ後のカウンタ値 = 11


こちらは、変更がループに影響します。
Exit Forを使わないで途中終了させることができます。
Exit Forは、まさにその時点で終了しますが、とりあえず今のループ処理だけは済ませたい場合に使い分けるといいでしょう。

■開始値、終了値、ステップ数が小数


'【コードウインドウ】
Private Sub testFor8() '開始値、終了値、ステップ数が小数
Dim For_cnt As Single, For_start As Single, For_end As Single, For_step As Single
For_start = 0.1
For_end = 0.5
For_step = 0.1

For For_cnt = For_start To For_end Step For_step
  Debug.Print "ループ中のカウンタ値 = " & For_cnt
Next For_cnt
Debug.Print "ループ後のカウンタ値 = " & For_cnt
End Sub

'【イミディエイトウインドウ】
ループ中のカウンタ値 = 0.1
ループ中のカウンタ値 = 0.2
ループ中のカウンタ値 = 0.3
ループ中のカウンタ値 = 0.4

ループ後のカウンタ値 = 0.5


For … Nextステートメントは小数も使用可能のようです。
おや、強制終了していないのにループ後のカウンタ値が終了値と同じです。
それ以前に、終了値に達するまでにループを抜けてしまっています。
これは…調査せねば!

        2009-12-27       ちょっと詳しく、For … Next

ちょっとしたマクロを組む時でも、繰り返し処理をする場面は多々あります。
基本的なFor … NextステートメントやDo … Loopステートメントをはじめ、再帰呼び出しやGoToステートメントなどで繰り返しをさせます。
この中でもっともお世話になるのがFor … Nextステートメントです。(少なくとも私はそう)
それだけに、VBAの入門書でも早々に紹介されています。

基本的な使い方はそちらにおまかせするとして、ここではもう少し掘り下げた内容を記事にしたいと思います。
For … Nextステートメントは、繰り返しのカウンタ値、開始値、終了値、ステップ数を指定します。
これらの値を色々と変えて、それぞれでカウンタ値がどう変化するかを調べます。
以下がひな形です。


'【コードウインドウ】
Private Sub testFor() 'ひな形
'左からカウンタ値開始値終了値ステップ用変数
Dim For_cnt As Long, For_start As Long, For_end As Long, For_step As Long
For For_cnt = For_start To For_end Step For_step '繰り返し、ここから
  Debug.Print "ループ中のカウンタ値 = " & For_cnt 'カウンタ値を表示
Next For_cnt '繰り返し、ここまで
Debug.Print "ループ後のカウンタ値 = " & For_cnt 'カウンタ値を表示
End Sub


■普通にループ


'【コードウインドウ】
Private Sub testFor1() '普通にループ
Dim For_cnt As Long, For_start As Long, For_end As Long, For_step As Long
For_start = 1
For_end = 5
For_step = 1

For For_cnt = For_start To For_end Step For_step
  Debug.Print "ループ中のカウンタ値 = " & For_cnt
Next For_cnt
Debug.Print "ループ後のカウンタ値 = " & For_cnt
End Sub

'【イミディエイトウインドウ】
ループ中のカウンタ値 = 1
ループ中のカウンタ値 = 2
ループ中のカウンタ値 = 3
ループ中のカウンタ値 = 4
ループ中のカウンタ値 = 5

ループ後のカウンタ値 = 6


注目すべきは、ループ終了後にカウンタ値が6になっていることです。
この6とは、ループ終了時のカウンタ値5に、ステップ数の1を足した値です。
後述しますが、これは非常に重要です。

■カウンタ値が2ずつ増加


'【コードウインドウ】
Private Sub testFor2() 'カウンタ値が2ずつ増加
Dim For_cnt As Long, For_start As Long, For_end As Long, For_step As Long
For_start = 1
For_end = 5
For_step = 2

For For_cnt = For_start To For_end Step For_step
  Debug.Print "ループ中のカウンタ値 = " & For_cnt
Next For_cnt
Debug.Print "ループ後のカウンタ値 = " & For_cnt
End Sub

'【イミディエイトウインドウ】
ループ中のカウンタ値 = 1
ループ中のカウンタ値 = 3
ループ中のカウンタ値 = 5

ループ後のカウンタ値 = 7


結果としては、testFor1と同じです。
ループ終了時にカウンタ値5に、ステップ数の2が足されています。

■カウンタ値が3ずつ増加


'【コードウインドウ】
Private Sub testFor3() 'カウンタ値が3ずつ増加
Dim For_cnt As Long, For_start As Long, For_end As Long, For_step As Long
For_start = 1
For_end = 5
For_step = 3

For For_cnt = For_start To For_end Step For_step
  Debug.Print "ループ中のカウンタ値 = " & For_cnt
Next For_cnt
Debug.Print "ループ後のカウンタ値 = " & For_cnt
End Sub

'【イミディエイトウインドウ】
ループ中のカウンタ値 = 1
ループ中のカウンタ値 = 4

ループ後のカウンタ値 = 7


カウンタ値が終了値を超えた時点でループが終了となりました。

■開始値が終了値より小さい


'【コードウインドウ】
Private Sub testFor1() '開始値が終了値より小さい
Dim For_cnt As Long, For_start As Long, For_end As Long, For_step As Long
For_start = 5
For_end = 1
For_step = 1

For For_cnt = For_start To For_end Step For_step
  Debug.Print "ループ中のカウンタ値 = " & For_cnt
Next For_cnt
Debug.Print "ループ後のカウンタ値 = " & For_cnt
End Sub

'【イミディエイトウインドウ】
ループ後のカウンタ値 = 5


開始値がすでに終了値より大きいため、何もせず終了しました。
エラーにはならないようです。

以上より、終了判定は値の大小であることがわかります。
また、ループを強制終了しなければ、カウンタ値は終了値より大きくなります
つまり、ループ後のカウンタ値を調べることで強制終了されたかどうかがわかるのです。
もし、終了時にステップ数が足されていなければ、最後のループで強制終了されるとどっちがどっちかわからなくなってしまいます。
以下は、実際に試してみるマクロです。
サイコロを1回振り、1の目が出ればループを強制終了すると想定しています。


'【コードウインドウ】
Private Sub testFor5() 'ループが強制終了されたかどうかを判定
Dim For_cnt As Long, For_start As Long, For_end As Long, For_step As Long
For_start = 1
For_end = 5
For_step = 1
For For_cnt = For_start To For_end Step For_step
  If Int(Rnd() * 6) + 1 = 1 Then '1~6の乱数が1なら
    Exit For 'ループを強制終了
  End If
Next For_cnt
If For_end < For_cnt Then 'カウンタが終了値より大きければ
  Debug.Print "すべてループされました"
Else
  Debug.Print "強制終了されました"
End If
End Sub

 | HOME | 

上記広告は1ヶ月以上更新のないブログに表示されています。新しい記事を書くことで広告を消せます。