2013-04-22 16 views
14

Jaki jest najbardziej wydajny i przenośny sposób generowania losowego losowego w [0,1] w Cython? Jednym ze sposobów jest użycie INT_MAX i rand() z biblioteki C:Prawidłowy sposób generowania liczb losowych w Cython?

from libc.stdlib cimport rand 
cdef extern from "limits.h": 
    int INT_MAX 
cdef float randnum = rand()/float(INT_MAX) 

Czy można używać INT_MAX w ten sposób? Zauważyłem, że jest zupełnie inny od stałej można uzyskać z Pythona max int:

import sys 
print INT_MAX 
print sys.maxint 

plony:

2147483647 (C max int) 
9223372036854775807 (python max int) 

Która jest właściwa „normalizacja” numer na rand()? EDIT dodatkowo, w jaki sposób można ustawić losowy materiał siewny (np. Zaszczepić w oparciu o bieżący czas), jeśli używa się metody C wywoływania rand() z biblioteki libc?

+0

Czy właśnie próbowałeś pobrać maksimum i minimum kilku tysięcy próbek i zobaczyć, który współczynnik skalowania zbliża się do wartości "1.0"? – phs

+0

Proszę uważać "[rand() za szkodliwe] (https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful)" –

Odpowiedz

8

Standard C mówi rand Zwraca int w zakresie od 0 do RAND_MAX włącznie, tak dzieląc ją przez RAND_MAX stdlib.h (z) jest to właściwy sposób normalizacji. W praktyce RAND_MAX prawie zawsze będzie równy MAX_INT, ale nie polegaj na tym.

Ponieważ rand jest częścią ISO C od C89, gwarantuje się, że będzie dostępna wszędzie, ale nie ma żadnych gwarancji dotyczących jakości losowych numerów. Jeśli przenośność jest Twoim głównym problemem, to jest to najlepsza opcja, chyba że chcesz korzystać z modułu Pythona random.

Python's sys.maxint to zupełnie inna koncepcja; jest to po prostu największa liczba dodatnia Python może reprezentować w własny typ; większe będą musiały być długie. Ints i longs Pythona nie są szczególnie związane z C.

+0

Dzięki! Czy wiesz, jak nasiona można ustawić za pomocą podejścia libc? – user248237dfsf

+1

Prawdopodobnie użyłbym 'random.randint (0, INT_MAX)'. Obciążenie nie stanowi problemu, ponieważ nastąpi to tylko raz. – Cairnarvon

+0

napowietrznych jest poważnym problemem, ponieważ nazywa się to wiele razy w pętli, która musi generować liczby losowe (w celu próbki z części wielomianowej w części). Czy mogę ustawić 'random.randint (0, INT_MAX)', a następnie wywołać 'rand()' C i mieć "zsynchronizowane" nasiona C i Pythona? – user248237dfsf

2

'c' stdlib rand() zwraca liczbę między 0 a RAND_MAX która jest ogólnie 32767.

Czy jest jakiś powód, aby nie używać python random()?

Generate random integers between 0 and 9

+0

Używam tej wewnętrznej pętli w funkcji Cython i wywoływania Pythona ponieważ jest to zbyt kosztowne – user248237dfsf

+0

RAND_MAX ma 2147483647 (2 ** 31-1) w moim systemie. Gwarantuje to przynajmniej * 2 ** 15-1, ale nie sądzę, żebym kiedykolwiek był tak niski w praktyce. – Cairnarvon

+0

Och, najwyraźniej msvc to 2 ** 15-1. To okropne. – Cairnarvon

1

Nie jestem pewien, czy drand jest nowym dodatkiem, ale wydaje się, że robi dokładnie to, czego chcesz, unikając kosztownego podziału.

cdef extern from "stdlib.h": 
    double drand48() 
    void srand48(long int seedval) 

cdef extern from "time.h": 
    long int time(int) 

# srand48(time(0)) 
srand48(100) 
# TODO: this is a seed to reproduce bugs, put to line of code above for 
# production 
drand48() #This gives a float in range [0,1) 

natknąłem this idea podczas badania, czy metoda podział generowane wystarczającą losowości. Źródło, które znalazłem, wskazuje, że w moim przypadku porównuję liczbę losową do dziesiętnej z dwiema cyframi, więc potrzebuję tylko 3 miejsc po przecinku. Więc INT_MAX jest więcej niż wystarczający. Wydaje się jednak, że drand48 oszczędza koszt podziału, więc warto go wykorzystać.

+2

Nawiasem mówiąc, nie jest to przenośne, ponieważ 'srand48' i' drand48' są dostępne tylko w systemach POSIX –

Powiązane problemy