privateRandom gen =newRandom();DateTimeRandomDay(){DateTime start =newDateTime(1995,1,1);int range =(DateTime.Today- start).Days;return start.AddDays(gen.Next(range));}
Aby uzyskać lepszą wydajność, jeśli będzie to wywoływane wielokrotnie, utwórz zmienne startand gen(a może nawet range) poza funkcją.
Losowość jest tylko pseudolosowa. Jeśli potrzebujesz naprawdę losowości, spróbuj użyć RNGCryptoServiceProvider z przestrzeni nazw System.Security.Cryptography.
tvanfosson
Dzięki tvanfosson. Do tego problemu wystarczy pseudolosowość.
Judah Gabriel Himango
5
Właściwie, Random nie jest nawet szczególnie pseudolosowy, chyba że trzymasz instancję przez jakiś czas i nadal uzyskujesz z niej wartości.
David Mitchell
2
Dlatego jest to tylko próbka, a nie kod produkcyjny.
Joel Coehoorn
1
Tak, to działa dla mnie; mój kod świata rzeczywistego będzie miał instancję Random poza samą metodą.
Judah Gabriel Himango
25
Jest to niewielka odpowiedź na komentarz Joela dotyczący stworzenia nieco bardziej zoptymalizowanej wersji. Zamiast zwracać losową datę bezpośrednio, dlaczego nie zwrócić funkcji generatora, którą można wielokrotnie wywoływać, aby utworzyć losową datę.
Func<DateTime>RandomDayFunc(){DateTime start =newDateTime(1995,1,1);Random gen =newRandom();int range =((TimeSpan)(DateTime.Today- start)).Days;return()=> start.AddDays(gen.Next(range));}
Czy możesz wyjaśnić, jak to jest korzystne? Nie można zamiast tego zacząć, gen i range być członkami klasy?
Mark A. Nicolosi,
Mogliby iw tym przypadku są. Pod maską wygeneruje to zamknięcie leksykalne, które jest klasą zawierającą początek, gen i zakres jako członków. To jest po prostu bardziej zwięzłe.
JaredPar
Niezła funkcja, mam tylko nadzieję, że nikt jej nie użyje jako:for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }
Aidiakapi
2
Jak jest używana ta funkcja, czy ktoś może wyjaśnić? Mam na myśli, jak mogę to nazwać?
Burak Karakuş
2
@ BurakKarakuş: Najpierw dostajesz fabrykę: var getRandomDate = RandomDayFunc();następnie dzwonisz do niej, aby uzyskać losowe daty: var randomDate = getRandomDate();Pamiętaj, że musisz ponownie użyć getRandomDate, aby było to bardziej przydatne niż odpowiedź Joela.
Şafak Gür
8
Wziąłem odpowiedź @Joel Coehoorn i wprowadziłem zmiany, które doradził - wyrzuciłem zmienną z metody i umieściłem wszystko w klasie. A teraz czas też jest losowy. Oto wynik.
classRandomDateTime{DateTime start;Random gen;int range;publicRandomDateTime(){
start =newDateTime(1995,1,1);
gen =newRandom();
range =(DateTime.Today- start).Days;}publicDateTimeNext(){return start.AddDays(gen.Next(range)).AddHours(gen.Next(0,24)).AddMinutes(gen.Next(0,60)).AddSeconds(gen.Next(0,60));}}
I przykład, jak użyć do zapisania 100 losowych DateTimes na konsoli:
RandomDateTime date =newRandomDateTime();for(int i =0; i <100; i++){Console.WriteLine(date.Next());}
Dlaczego dwukrotnie tworzysz Random ()? Raz w klasie deklaracja gen zmiennej a innym razem w c-tor?
piksel
Tak, raz wystarczy. Naprawiłem to.
prespicion
1
Wygenerowanie tylko jednej losowej liczby sekund i dodanie jej do daty rozpoczęcia jest około cztery razy szybsze: range = (int)(DateTime.Today - start).TotalSeconds;i return start.AddSeconds(gen.Next(range));.
Jurgy,
5
Cóż, jeśli chcesz przedstawić alternatywną optymalizację, możemy również wybrać iterator:
staticIEnumerable<DateTime>RandomDay(){DateTime start =newDateTime(1995,1,1);Random gen =newRandom();int range =((TimeSpan)(DateTime.Today- start)).Days;while(true)yieldreturn start.AddDays(gen.Next(range));}
możesz tego użyć w ten sposób:
int i=0;foreach(DateTime dt inRandomDay()){Console.WriteLine(dt);if(++i ==10)break;}
Jedną rzeczą do rozważenia między iteratorem a funkcją generatora jest to, że rozwiązanie iteratora wygeneruje wartość IDisposable. Zmusza to dzwoniącego do pozbycia się lub zapłacenia ceny za umieszczenie finalizatora w GC. Generator nie wymaga utylizacji
JaredPar
2
@JaredPar, to nie do końca w porządku. Tylko dlatego, że typ implementuje IDisposable, nie oznacza, że można go sfinalizować.
Drew Noakes
3
Zacznij od obiektu z ustaloną datą (1 stycznia 1995) i dodaj losową liczbę dni za pomocą AddDays (oczywiście, zwróć uwagę, aby nie przekroczyć bieżącej daty).
Dzięki Friol. Miałem zapytać, jak ograniczyć liczbę przekazywaną do losowej. Joel opublikował przykład z przykładowym kodem, więc oznaczę jego odpowiedź jako odpowiedź.
Judah Gabriel Himango,
0
Jestem trochę za późno w grze, ale oto jedno rozwiązanie, które działa dobrze:
voidMain(){var dateResult =GetRandomDates(newDateTime(1995,1,1),DateTime.UtcNow,100);foreach(var r in dateResult)Console.WriteLine(r);}publicstaticIList<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;}publicstaticIEnumerable<int>GetRandomNumbers(int size){var data =newbyte[4];
using (var rng =newSystem.Security.Cryptography.RNGCryptoServiceProvider(data)){for(int i =0; i < size; i++){
rng.GetBytes(data);varvalue=BitConverter.ToInt32(data,0);yieldreturnvalue<0?value*-1:value;}}}
Mała metoda, która zwraca losową datę w postaci ciągu na podstawie kilku prostych parametrów wejściowych. Zbudowany na podstawie odchyleń od powyższych odpowiedzi:
publicstringRandomDate(int startYear =1960,string outputDateFormat ="yyyy-MM-dd"){DateTime start =newDateTime(startYear,1,1);Random gen =newRandom(Guid.NewGuid().GetHashCode());int range =(DateTime.Today- start).Days;return start.AddDays(gen.Next(range)).ToString(outputDateFormat);}
Odpowiedzi:
Aby uzyskać lepszą wydajność, jeśli będzie to wywoływane wielokrotnie, utwórz zmienne
start
andgen
(a może nawetrange
) poza funkcją.źródło
Jest to niewielka odpowiedź na komentarz Joela dotyczący stworzenia nieco bardziej zoptymalizowanej wersji. Zamiast zwracać losową datę bezpośrednio, dlaczego nie zwrócić funkcji generatora, którą można wielokrotnie wywoływać, aby utworzyć losową datę.
źródło
for (int i = 0; i < 100; i++) { array[i].DateProp = RandomDayFunc()(); }
var getRandomDate = RandomDayFunc();
następnie dzwonisz do niej, aby uzyskać losowe daty:var randomDate = getRandomDate();
Pamiętaj, że musisz ponownie użyć getRandomDate, aby było to bardziej przydatne niż odpowiedź Joela.Wziąłem odpowiedź @Joel Coehoorn i wprowadziłem zmiany, które doradził - wyrzuciłem zmienną z metody i umieściłem wszystko w klasie. A teraz czas też jest losowy. Oto wynik.
I przykład, jak użyć do zapisania 100 losowych DateTimes na konsoli:
źródło
range = (int)(DateTime.Today - start).TotalSeconds;
ireturn start.AddSeconds(gen.Next(range));
.Cóż, jeśli chcesz przedstawić alternatywną optymalizację, możemy również wybrać iterator:
możesz tego użyć w ten sposób:
źródło
Zacznij od obiektu z ustaloną datą (1 stycznia 1995) i dodaj losową liczbę dni za pomocą AddDays (oczywiście, zwróć uwagę, aby nie przekroczyć bieżącej daty).
źródło
Jestem trochę za późno w grze, ale oto jedno rozwiązanie, które działa dobrze:
źródło
Mała metoda, która zwraca losową datę w postaci ciągu na podstawie kilku prostych parametrów wejściowych. Zbudowany na podstawie odchyleń od powyższych odpowiedzi:
źródło