private Random gen = new Random();
DateTime RandomDay()
{
DateTime start = new DateTime(1995, 1, 1);
int range = (DateTime.Today - start).Days;
return start.AddDays(gen.Next(range));
}
Untuk kinerja yang lebih baik jika ini akan dipanggil berulang kali, buat variabel startdan gen(dan mungkin bahkan range) di luar fungsi.
Acak hanyalah pseudo-random. Jika Anda benar-benar perlu acak, coba gunakan RNGCryptoServiceProvider dari namespace System.Security.Cryptography.
tvanfosson
Terima kasih tvanfosson. Pseudo-random cukup untuk masalah ini.
Judah Gabriel Himango
5
Sebenarnya, Random bahkan bukan pseudo-random kecuali Anda menyimpan instance untuk sementara dan terus mendapatkan nilai darinya.
David Mitchell
2
Itulah mengapa ini hanya contoh, bukan kode produksi.
Joel Coehoorn
1
Ya, itu berhasil untuk saya; kode dunia nyata saya akan memiliki contoh Acak di luar metode itu sendiri.
Judah Gabriel Himango
26
Ini adalah tanggapan kecil atas komentar Joel tentang membuat versi yang sedikit lebih dioptimalkan. Daripada mengembalikan tanggal acak secara langsung, mengapa tidak mengembalikan fungsi generator yang bisa dipanggil berulang kali untuk membuat tanggal acak.
Func<DateTime> RandomDayFunc()
{
DateTime start = new DateTime(1995, 1, 1);
Random gen = new Random();
int range = ((TimeSpan)(DateTime.Today - start)).Days;
return () => start.AddDays(gen.Next(range));
}
Bisakah Anda menjelaskan bagaimana ini bermanfaat? Tidak dapat memulai, gen, dan rentang menjadi anggota kelas sebagai gantinya?
Mark A. Nicolosi
Mereka bisa dan dalam hal ini mereka. Di bawah tenda ini akan menghasilkan penutupan leksikal yang merupakan kelas yang berisi start, gen dan range sebagai anggota. Ini hanya lebih ringkas.
JaredPar
Fungsi yang bagus, saya hanya berharap tidak ada yang akan menggunakannya sebagai:for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }
Aidiakapi
2
Bagaimana fungsi ini digunakan, bisakah seseorang menjelaskan? Maksud saya bagaimana saya bisa menyebutnya?
Burak Karakuş
2
@ BurakKarakuş: Anda mendapatkan pabrik terlebih dahulu: var getRandomDate = RandomDayFunc();kemudian Anda menyebutnya untuk mendapatkan tanggal acak: var randomDate = getRandomDate();Ingatlah bahwa Anda perlu menggunakan kembali getRandomDate agar ini lebih berguna daripada jawaban Joel.
Şafak Gür
9
Saya telah mengambil jawaban @Joel Coehoorn dan membuat perubahan yang dia sarankan - keluarkan variabel dari metode dan taruh semuanya di kelas. Ditambah sekarang waktunya juga acak. Inilah hasilnya.
classRandomDateTime
{
DateTime start;
Random gen;
int range;
publicRandomDateTime()
{
start = new DateTime(1995, 1, 1);
gen = new Random();
range = (DateTime.Today - start).Days;
}
public DateTime Next()
{
return start.AddDays(gen.Next(range)).AddHours(gen.Next(0,24)).AddMinutes(gen.Next(0,60)).AddSeconds(gen.Next(0,60));
}
}
Dan contoh bagaimana menggunakan untuk menulis 100 DateTimes acak ke konsol:
RandomDateTime date = new RandomDateTime();
for (int i = 0; i < 100; i++)
{
Console.WriteLine(date.Next());
}
Mengapa Anda membuat Random () dua kali? Setelah di deklarasi gen variabel kelas dan waktu lain di c-tor?
piksel
Ya, sekali saja sudah cukup. Aku telah memperbaikinya.
prespic
1
Ini sekitar empat kali lebih cepat untuk menghasilkan hanya satu angka acak dari detik dan menambahkannya ke tanggal mulai Anda: range = (int)(DateTime.Today - start).TotalSeconds;dan return start.AddSeconds(gen.Next(range));.
Jurgen
5
Nah, jika Anda ingin menampilkan pengoptimalan alternatif, kami juga dapat menggunakan iterator:
static IEnumerable<DateTime> RandomDay()
{
DateTime start = new DateTime(1995, 1, 1);
Random gen = new Random();
int range = ((TimeSpan)(DateTime.Today - start)).Days;
while (true)
yieldreturn start.AddDays(gen.Next(range));
}
Anda bisa menggunakannya seperti ini:
int i=0;
foreach(DateTime dt inRandomDay())
{
Console.WriteLine(dt);
if (++i == 10)
break;
}
Satu hal yang perlu diperhatikan antara fungsi iterator vs generator adalah bahwa solusi iterator akan menghasilkan nilai IDisposable. Ini memaksa penelepon untuk membuang atau membayar harga untuk memiliki finalizer yang tinggal di GC. Generator tidak perlu dibuang
JaredPar
2
@JaredPar, itu kurang tepat. Hanya karena suatu tipe mengimplementasikan IDisposable tidak berarti itu dapat diselesaikan.
Drew Noakes
3
Mulailah dengan objek tanggal tetap (Jan 1, 1995), dan tambahkan jumlah hari acak dengan AddDays (jelas-jelas, perhatikan tidak melebihi tanggal saat ini).
Terima kasih Friol. Saya akan bertanya bagaimana membatasi nomor yang diteruskan menjadi acak. Joel telah memposting contoh dengan contoh kode, jadi saya akan menandai tanggapannya sebagai jawabannya.
Judah Gabriel Himango
0
Saya agak terlambat dalam permainan ini, tetapi berikut adalah satu solusi yang berfungsi dengan baik:
voidMain()
{
var dateResult = GetRandomDates(new DateTime(1995, 1, 1), DateTime.UtcNow, 100);
foreach (var r in dateResult)
Console.WriteLine(r);
}
publicstatic IList<DateTime> GetRandomDates(DateTime startDate, DateTime maxDate, int range)
{
var randomResult = GetRandomNumbers(range).ToArray();
var calculationValue = maxDate.Subtract(startDate).TotalMinutes / int.MaxValue;
var dateResults = randomResult.Select(s => startDate.AddMinutes(s * calculationValue)).ToList();
return dateResults;
}
publicstatic IEnumerable<int> GetRandomNumbers(int size)
{
var data = newbyte[4];
using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider(data))
{
for (int i = 0; i < size; i++)
{
rng.GetBytes(data);
varvalue = BitConverter.ToInt32(data, 0);
yieldreturnvalue < 0 ? value * -1 : value;
}
}
}
Metode kecil yang mengembalikan tanggal acak sebagai string, berdasarkan beberapa parameter masukan sederhana. Dibangun berdasarkan variasi dari jawaban di atas:
publicstringRandomDate(int startYear = 1960, string outputDateFormat = "yyyy-MM-dd")
{
DateTime start = new DateTime(startYear, 1, 1);
Random gen = new Random(Guid.NewGuid().GetHashCode());
int range = (DateTime.Today - start).Days;
return start.AddDays(gen.Next(range)).ToString(outputDateFormat);
}
Jawaban:
private Random gen = new Random(); DateTime RandomDay() { DateTime start = new DateTime(1995, 1, 1); int range = (DateTime.Today - start).Days; return start.AddDays(gen.Next(range)); }
Untuk kinerja yang lebih baik jika ini akan dipanggil berulang kali, buat variabel
start
dangen
(dan mungkin bahkanrange
) di luar fungsi.sumber
Ini adalah tanggapan kecil atas komentar Joel tentang membuat versi yang sedikit lebih dioptimalkan. Daripada mengembalikan tanggal acak secara langsung, mengapa tidak mengembalikan fungsi generator yang bisa dipanggil berulang kali untuk membuat tanggal acak.
Func<DateTime> RandomDayFunc() { DateTime start = new DateTime(1995, 1, 1); Random gen = new Random(); int range = ((TimeSpan)(DateTime.Today - start)).Days; return () => start.AddDays(gen.Next(range)); }
sumber
for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }
var getRandomDate = RandomDayFunc();
kemudian Anda menyebutnya untuk mendapatkan tanggal acak:var randomDate = getRandomDate();
Ingatlah bahwa Anda perlu menggunakan kembali getRandomDate agar ini lebih berguna daripada jawaban Joel.Saya telah mengambil jawaban @Joel Coehoorn dan membuat perubahan yang dia sarankan - keluarkan variabel dari metode dan taruh semuanya di kelas. Ditambah sekarang waktunya juga acak. Inilah hasilnya.
class RandomDateTime { DateTime start; Random gen; int range; public RandomDateTime() { start = new DateTime(1995, 1, 1); gen = new Random(); range = (DateTime.Today - start).Days; } public DateTime Next() { return start.AddDays(gen.Next(range)).AddHours(gen.Next(0,24)).AddMinutes(gen.Next(0,60)).AddSeconds(gen.Next(0,60)); } }
Dan contoh bagaimana menggunakan untuk menulis 100 DateTimes acak ke konsol:
RandomDateTime date = new RandomDateTime(); for (int i = 0; i < 100; i++) { Console.WriteLine(date.Next()); }
sumber
range = (int)(DateTime.Today - start).TotalSeconds;
danreturn start.AddSeconds(gen.Next(range));
.Nah, jika Anda ingin menampilkan pengoptimalan alternatif, kami juga dapat menggunakan iterator:
static IEnumerable<DateTime> RandomDay() { DateTime start = new DateTime(1995, 1, 1); Random gen = new Random(); int range = ((TimeSpan)(DateTime.Today - start)).Days; while (true) yield return start.AddDays(gen.Next(range)); }
Anda bisa menggunakannya seperti ini:
int i=0; foreach(DateTime dt in RandomDay()) { Console.WriteLine(dt); if (++i == 10) break; }
sumber
Mulailah dengan objek tanggal tetap (Jan 1, 1995), dan tambahkan jumlah hari acak dengan AddDays (jelas-jelas, perhatikan tidak melebihi tanggal saat ini).
sumber
Saya agak terlambat dalam permainan ini, tetapi berikut adalah satu solusi yang berfungsi dengan baik:
void Main() { var dateResult = GetRandomDates(new DateTime(1995, 1, 1), DateTime.UtcNow, 100); foreach (var r in dateResult) Console.WriteLine(r); } public static IList<DateTime> GetRandomDates(DateTime startDate, DateTime maxDate, int range) { var randomResult = GetRandomNumbers(range).ToArray(); var calculationValue = maxDate.Subtract(startDate).TotalMinutes / int.MaxValue; var dateResults = randomResult.Select(s => startDate.AddMinutes(s * calculationValue)).ToList(); return dateResults; } public static IEnumerable<int> GetRandomNumbers(int size) { var data = new byte[4]; using (var rng = new System.Security.Cryptography.RNGCryptoServiceProvider(data)) { for (int i = 0; i < size; i++) { rng.GetBytes(data); var value = BitConverter.ToInt32(data, 0); yield return value < 0 ? value * -1 : value; } } }
sumber
Metode kecil yang mengembalikan tanggal acak sebagai string, berdasarkan beberapa parameter masukan sederhana. Dibangun berdasarkan variasi dari jawaban di atas:
public string RandomDate(int startYear = 1960, string outputDateFormat = "yyyy-MM-dd") { DateTime start = new DateTime(startYear, 1, 1); Random gen = new Random(Guid.NewGuid().GetHashCode()); int range = (DateTime.Today - start).Days; return start.AddDays(gen.Next(range)).ToString(outputDateFormat); }
sumber