C# と VB.NET の質問掲示板

ASP.NET、C++/CLI、Java 何でもどうぞ

C# と VB.NET の入門サイト

Re[10]: 日付をランダムに取得したい


(過去ログ 85 を表示中)

[トピック内 15 記事 (1 - 15 表示)]  << 0 >>

■50429 / inTopicNo.1)  日付をランダムに取得したい
  
□投稿者/ カルメン (4回)-(2010/06/07(Mon) 10:30:42)

分類:[VB.NET/VB2005 以降] 

いつもお世話になっております。

VB2008です。
本日から1年前までのランダムな日付を取得したいのですが、方法がわかりません。
VBAだと下記で出来たのですが、VB2008だとどのような方法がありますか?

宜しくお願い致します。

    Dim dteUpperDate As Date
    Dim dteLowerDate As Date
    
    dteUpperDate = Now
    dteLowerDate = DateAdd("yyyy", -1, Now)
    
    Randomize
    GetRandomDate = Int((dteUpperDate - dteLowerDate + 1) * Rnd + dteLowerDate)

引用返信 編集キー/
■50430 / inTopicNo.2)  Re[1]: 日付をランダムに取得したい
□投稿者/ かたぎり (28回)-(2010/06/07(Mon) 10:43:24)
ランダム値を0〜-364の間で生成して、それにDateAdd、でいいと思いまする。
引用返信 編集キー/
■50431 / inTopicNo.3)  Re[2]: 日付をランダムに取得したい
□投稿者/ みきぬ (914回)-(2010/06/07(Mon) 10:47:51)
・1年前の日付を含むのか(当日はおそらく含むんだろうけど)
・そもそも1年前とはどういう定義なのか(例えば、今日が2008/2/29の場合)
・↑にも関連するけど閏年の考慮

とまあ、考えることはいろいろあると思うけど頑張ってください。
引用返信 編集キー/
■50433 / inTopicNo.4)  Re[1]: 日付をランダムに取得したい
□投稿者/ よねKEN (519回)-(2010/06/07(Mon) 10:56:11)
よねKEN さんの Web サイト
2010/06/07(Mon) 10:57:28 編集(投稿者)

No50429 (カルメン さん) に返信
> VBAだと下記で出来たのですが、VB2008だとどのような方法がありますか?

(1) VBAのロジックそのまんま

> Dim dteUpperDate As Date
> Dim dteLowerDate As Date
>
> dteUpperDate = Now
> dteLowerDate = DateAdd("yyyy", -1, Now)
>
> Randomize
> GetRandomDate = Int((dteUpperDate - dteLowerDate + 1) * Rnd + dteLowerDate)
GetRandomDate = Date.FromOADate(Int((dteUpperDate.ToOADate() - dteLowerDate.ToOADate() + 1) * Rnd + dteLowerDate.ToOADate()))

のようにToOADateメソッド、FromOADateメソッドを使うことで、元のソースコードのやり方を踏襲することもできます。
※厳密に一致しているかは、未検証ですが・・・

(2) .NET流な感じで
Dim upperDate As Date = Date.Today
Dim lowerDate As Date = upperDate.AddYears(-1)
Dim span As TimeSpan = upperDate - lowerDate
Dim rnd As new Random()
GetRandomDate = lowerDate.AddDays(rnd.Next(span.Days + 1))

※(1)、(2)ともに1年前の日付がいつであるべきかとかは特に検討していませんので、
 カルメンさんの仕様と合致しているかどうかはわかりません。
※(2)はファイルの先頭に「Imports System」のように記述してある前提のコード

引用返信 編集キー/
■50473 / inTopicNo.5)  Re[2]: 日付をランダムに取得したい
□投稿者/ カルメン (6回)-(2010/06/08(Tue) 14:31:56)
かたぎり様、みきぬ様、よねKEN様、ありがとうございます。

よねKEN様の方法、どちらも出来ました。
これを1つの関数として組み込んでいますが、(2)の方法だと
10回ループしたとして、10回全て同じ日付が返ってきます。
(デバッグしながらだと違う日付が返ります。)

重複させないようにするにはどうしたらよいのでしょうか?

宜しくお願い致します。
引用返信 編集キー/
■50474 / inTopicNo.6)  Re[3]: 日付をランダムに取得したい
□投稿者/ 中 博俊 (1回)-(2010/06/08(Tue) 14:40:17)
Randomクラスを作り直してはいけないからです。
アプリ内でシングルトンにしてください。
引用返信 編集キー/
■50475 / inTopicNo.7)  Re[4]: 日付をランダムに取得したい
□投稿者/ なちゃ (444回)-(2010/06/08(Tue) 14:49:55)
マルチスレッドには注意してね
引用返信 編集キー/
■50480 / inTopicNo.8)  Re[3]: 日付をランダムに取得したい
□投稿者/ よねKEN (520回)-(2010/06/08(Tue) 15:46:06)
よねKEN さんの Web サイト
No50473 (カルメン さん) に返信
> これを1つの関数として組み込んでいますが、(2)の方法だと
> 10回ループしたとして、10回全て同じ日付が返ってきます。

(1)も(2)も提示のコードは、考え方はまったく同じなので、
ループの中に上記の処理を組み込んだ場合、(1)(2)のどちらの場合も不都合な結果になる可能性はあります。
(VB固有のRandomize、Rndは内部的にSystem.Randomを使っていないようなので動作結果は違うのかもしれませんが)

> 重複させないようにするにはどうしたらよいのでしょうか?

こちらについては中さんのご指摘の通りですが、もう少し補足しておきます。

乱数を扱う機能は、

1. どんな乱数列を使うかを決定する
  →例えば、3187, 28912, 2 , 10 2093, ・・・ というような乱数列に決まったとする
2. 最初に決めた乱数列から乱数を取り出す
  →1回目は3187
3. 2.を繰り返す
  →2回目は28912
   3回目は2
   4回目は...


というような処理手順を踏んで使用します。

1.の部分に当たるのが、(1)ならRandomizeステートメント、(2)ならNew Random()の箇所です。
通常はこの1.の手順はアプリ内で1度だけ処理します。←ここが対処方法

RandomizeステートメントもNew Random()も引数を取る事ができ、そこで指定した値から
どんな乱数列を使用するかが決定されます。この値のことをシード(種)といいます。
同じシードを与えてやると毎回同じ乱数列を発生させることができます。

今回の提示コードのように引数を取らない場合、シードとしてシステム時刻が使われ、乱数列が決定されます。

で、10回のループは一瞬の処理なので、「New Random()」を実行するときのシステム時刻が同時刻になっているものと思います。
そうすると同じシードを与えて乱数列を作っていることになるので、毎ループで同じ乱数列を指定して、
その先頭の数値を取得していることになります。
(上の処理手順の例では、常に3187を取るような処理になっている、ということ)

というのが原因になります。

引用返信 編集キー/
■50482 / inTopicNo.9)  Re[4]: 日付をランダムに取得したい
□投稿者/ カルメン (7回)-(2010/06/08(Tue) 15:55:46)
中様、なちゃ様、よねKEN様、ありがとうございます。

特によねKEN様、詳しい説明ありがとうございました。
原因がよくわかりました。

中様、なちゃ様から教えて頂いた事を調べながらやってみます。


引用返信 編集キー/
■50544 / inTopicNo.10)  Re[5]: 日付をランダムに取得したい
□投稿者/ カルメン (8回)-(2010/06/10(Thu) 15:48:23)
シングルトン…、調べたのですが使用方法がよくわかりませんでした…。

申し訳ないのですが教えて頂けないでしょうか…?

宜しくお願い致します。
引用返信 編集キー/
■50555 / inTopicNo.11)  Re[6]: 日付をランダムに取得したい
□投稿者/ みきぬ (917回)-(2010/06/10(Thu) 17:03:57)
No50544 (カルメン さん) に返信
> シングルトン…、調べたのですが使用方法がよくわかりませんでした…。
>
> 申し訳ないのですが教えて頂けないでしょうか…?
>
> 宜しくお願い致します。

Singleton パターンまで調べなくても、 No50480 のよねKEN氏の説明が理解できたのなら大丈夫ですよ。
具体的にどう直せばよいかという話であれば、まず現在は VB2008 でどう書いているのかを説明したほうがいいのではないかな、と。
引用返信 編集キー/
■50557 / inTopicNo.12)  Re[7]: 日付をランダムに取得したい
□投稿者/ マサヤ (11回)-(2010/06/10(Thu) 17:26:54)
2010/06/10(Thu) 17:37:10 編集(投稿者)
2010/06/10(Thu) 17:33:33 編集(投稿者)

No50544 (カルメン さん) に返信
>シングルトン…、調べたのですが使用方法がよくわかりませんでした…。
>
>申し訳ないのですが教えて頂けないでしょうか…?
>
>宜しくお願い致します。

http://msdn.microsoft.com/en-us/library/ff650316.aspx
ここをみるとシングルトンについて書いてあります。

singletonで日付の365日分のインスタンスを持ち続けるようにします。
そのインスタンスに対してRandomで取り出せばいいのではないのか、ということだと思います。



引用返信 編集キー/
■50571 / inTopicNo.13)  Re[8]: 日付をランダムに取得したい
□投稿者/ カルメン (9回)-(2010/06/11(Fri) 08:57:52)
みきぬ様、マサヤ様、ありがとうございます。

マサヤ様の教えてくださったURL、あとでじっくり読ませて頂きます。

下記の方法でランダムな日付を取得する事が出来ました。

Public Class frmMain

    Private msysRandom As New Random

    Private Function GetRandomDate(ByVal DateFormat As String) As String
        Dim LowerDate As Date = Today.AddYears(-1)
        Dim RandomDate As Date
        Dim DateSpan As Integer

        DateSpan = msysRandom.Next(1, 365)
        RandomDate = LowerDate.AddDays(DateSpan)
        GetRandomDate = RandomDate.ToString(DateFormat)
    End Function
End Class

インスタンスは1つのみ、と理解したのでクラス変数としたのですが、正しいでしょうか?

宜しくお願い致します。

引用返信 編集キー/
■50572 / inTopicNo.14)  Re[9]: 日付をランダムに取得したい
□投稿者/ よねKEN (521回)-(2010/06/11(Fri) 09:21:12)
よねKEN さんの Web サイト
No50571 (カルメン さん) に返信
> DateSpan = msysRandom.Next(1, 365)

うるう年が絡む場合が考慮さていませんが、その点は大丈夫ですか?

> インスタンスは1つのみ、と理解したのでクラス変数としたのですが、正しいでしょうか?

はい、OKだと思います。

#細かい話ですが「Private msysRandom As New Random」のことは
#インスタンス変数、インスタンスフィールドなどと呼ぶ方がよいと思います。
#一般的に「クラス変数」というと、クラスに対して単一の変数=静的フィールド、共有フィールド
#(VBで言うとShared付きで宣言したフィールド)を意味するためです。

引用返信 編集キー/
■50575 / inTopicNo.15)  Re[10]: 日付をランダムに取得したい
□投稿者/ カルメン (10回)-(2010/06/11(Fri) 10:19:45)
No50572 (よねKEN さん) に返信
> うるう年が絡む場合が考慮さていませんが、その点は大丈夫ですか?

そうですね、下記のように対応します。

Dim upperDate As Date = Date.Today
Dim lowerDate As Date = upperDate.AddYears(-1)
Dim span As TimeSpan = upperDate - lowerDate

> #細かい話ですが「Private msysRandom As New Random」のことは
> #インスタンス変数、インスタンスフィールドなどと呼ぶ方がよいと思います。
> #一般的に「クラス変数」というと、クラスに対して単一の変数=静的フィールド、共有フィールド
> #(VBで言うとShared付きで宣言したフィールド)を意味するためです。
詳しく説明してくださりありがとうございます。
これからはそのように呼びます。

皆様のおかげで無事完成させる事が出来ました。
ありがとうございました。
解決済み
引用返信 編集キー/


トピック内ページ移動 / << 0 >>

このトピックに書きこむ

過去ログには書き込み不可

管理者用

- Child Tree -