2013-04-22 2 views
14

Что представляет собой самый эффективный и портативный способ генерации случайного случайного числа в [0,1] в Китоне? Один из подходов заключается в использовании INT_MAX и rand() из библиотеки C:Правильный способ генерации случайных чисел в Cython?

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

Допустимо ли использовать INT_MAX таким образом? Я заметил, что она сильно отличается от константы вы получите от макс междунара Пайтона:

import sys 
print INT_MAX 
print sys.maxint 

выходов:

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

Который является правильной «нормализация» номер для rand()? EDIT Кроме того, как можно установить случайное семя (например, затраченное на текущее время), если использовать метод C для вызова rand() из libc?

+0

Вы только что попробовали взять max и min из нескольких тысяч выборок и посмотреть, какой масштабный коэффициент приближается к '1.0'? – phs

+0

Пожалуйста, смотрите «[rand() считается вредным] (https://channel9.msdn.com/Events/GoingNative/2013/rand-Considered-Harmful)« –

ответ

8

Стандарт С говорит rand возвращается в диапазоне от 0 до int в RAND_MAX включительно, таким образом разделив его на RAND_MAX (от stdlib.h) является правильный способ ее нормализации. На практике RAND_MAX почти всегда будет равен MAX_INT, но не полагайтесь на это.

Поскольку rand был частью ISO C начиная с C89, он гарантированно будет доступен везде, но не гарантируется качество его случайных чисел. Если переносимость - это ваша главная проблема, это ваш лучший вариант, если вы не хотите использовать модуль P.

Python's sys.maxint - это совершенно другая концепция; это просто наибольшее положительное число, которое Python может представлять в свой собственный тип int; более крупные должны быть длинными. Python ints и longs не имеют особого отношения к C.

+0

Спасибо! Знаете ли вы, как семя может быть установлено с использованием подхода libc? – user248237dfsf

+1

Я бы, наверное, использовал 'random.randint (0, INT_MAX)' для этого. Накладные расходы не являются проблемой, потому что это произойдет только один раз. – Cairnarvon

+0

Накладные расходы являются серьезной проблемой, так как это называется много раз в цикле, который должен генерировать случайные числа (для того, чтобы отбирать из нескольких многочленов частично). Могу ли я установить «random.randint (0, INT_MAX)», а затем вызвать «rand()» и «C» и «Python» будут синхронизироваться? – user248237dfsf

2

«с» Rand STDLIB() возвращает число от 0 до RAND_MAX который обычно 32767.

Есть ли какая-либо причина не использовать питон случайного()?

Generate random integers between 0 and 9

+0

Я использую этот внутренний цикл в функции Cython и вызывая Python потому что это слишком дорого. – user248237dfsf

+0

RAND_MAX - 2147483647 (2 ** 31-1) в моей системе. Это гарантированно будет * как минимум * 2 ** 15-1, но я не думаю, что когда-либо видел это на практике. – Cairnarvon

+0

О, очевидно, msvc's 2 ** 15-1. Это ужасно. – Cairnarvon

1

Я не уверен, что drand - это новое дополнение, но оно, похоже, делает именно то, что вы хотите, избегая дорогостоящего разделения.

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) 

я наткнулся this idea при исследовании, если ваш метод деления генерируется достаточной хаотичность. Источник, который я нашел, делает хорошую точку зрения, что в моем случае я сравниваю случайное число с десятичной цифрой с двумя цифрами, поэтому мне действительно нужны только 3 десятичные точки точности. Поэтому INT_MAX более чем достаточно. Но, похоже, drand48 экономит затраты на деление, поэтому его стоит использовать.

+2

Кстати, это не переносимо, потому что 'srand48' и' drand48' доступны только в системах POSIX –

Смежные вопросы