Как получить случайное число BigInt в пределах диапазона в Джулии?

Мне нужно получить случайное число между 1 и BigInt в Джулии, но я не смог найти в документации, как это можно сделать. Ниже приведен код, который, как я думал, будет работать:

julia> rand(BigInt(1):BigInt(2^1000))
ERROR: integer division error
 in randu at random.jl:158
 in rand at random.jl:178
 in rand at random.jl:187

изменить: GregS упомянул, что 2^1000 будет обернут вокруг нуля. На самом деле 2^1000 дает ноль, поэтому приведенный выше код неверен. Но использование BigInt(2)^1000 не работает:

julia> rand(BigInt(1):BigInt(2)^1000)
ERROR: InexactError()
 in convert at gmp.jl:108
 in colon at range.jl:38

julia> rand(BigInt(1):BigInt(2)^BigInt(1000))
ERROR: InexactError()
 in convert at gmp.jl:108
 in colon at range.jl:38

Каков самый быстрый способ сделать это? (Числа должны быть распределены равномерно).

Спасибо!


person Jay    schedule 24.07.2014    source источник
comment
Это должно сработать, пожалуйста, отправьте заявку.   -  person StefanKarpinski    schedule 25.07.2014
comment
Я не знаю, Джулия, но, может быть, 2 ^ 1000 сначала обернутся до нуля. Возможно, BigInt(2)^1000 будет работать лучше.   -  person President James K. Polk    schedule 25.07.2014
comment
Мне кажется, что это в настоящее время не поддерживается. rand(BigInt(1)) приводит к ОШИБКЕ: rand не имеет метода, соответствующего rand(::BigInt), и вариант Range просто пытается выполнить вычисления, используя вариант без диапазона. Можете ли вы обойтись с Int128, пока не будет исправлено?   -  person waTeim    schedule 26.07.2014
comment
Это прошло много времени после исходного сообщения, но rand(1:big"2"^1000) теперь отлично работает для меня в Julia 1.1.0.   -  person Julia Learner    schedule 01.02.2019


Ответы (2)


В конце концов, это доступно, если вы используете ccall. Я уверен, что в какой-то момент это будет легко, но вот способ сделать это сейчас, я не нашел способа использовать его из базы, но внесу поправку, если что-то изменится. Для этого необходимо сделать 2 вызова. Из документов gmp я выбрал mpz_urandomm.

Поддержка GMP

— Функция: void mpz_urandomm (mpz_t rop, gmp_randstate_t state, const mpz_t n) Генерирует равномерное случайное целое число в диапазоне от 0 до n-1 включительно.

Состояние переменной должно быть инициализировано вызовом одной из функций gmp_randinit (инициализация случайного состояния) перед вызовом этой функции.

Сначала нужно инициализировать генератор случайных чисел, я сделал это не оптимально, буду обновлять что-то дорабатывать.

— Функция: void gmp_randinit_default (состояние gmp_randstate_t) Инициализировать состояние с помощью алгоритма по умолчанию. Это будет компромисс между скоростью и случайностью и рекомендуется для приложений без особых требований. В настоящее время это gmp_randinit_mt.

метод вызова

Инициализировать ГСЧ

Не имея элегантного способа объявить gmp_randstate_t, просто объявите большой буфер. Это важно, иначе произойдет segfault.

julia> buffer = Array(Uint8,32);
julia> ccall((:__gmp_randinit_default,:libgmp),Void,(Ptr{Uint8},),buffer);

Генерация случайных чисел

Создайте BigInt, x для сохранения результата

julia> x = BigInt(0)
0

Установите y на MaxRange

Юлия> у = BigInt(2)^1000

10715086071862673209484250490600018105614048117055336074437503883703510511249361224931983788156958581275946729175531468251871452856923140435984577574698574803934567774824230985421074605062371141877954182153046474983581941267398767559165543946077062914571196477686542167660429831652624386837205668069376

Создать случайный х

julia> ccall((:__gmpz_urandomm,:libgmp),Void,(Ptr{BigInt},Ptr{Uint8},Ptr{BigInt}),&x,buffer,&y)

проверять

джулия> х 9301165293246235069759966068146313776551258669855356477271940698500929939755418247622530571466332330697816620308003246225290293476785304004840090056840661553451916748315356563734257724978000166406621823207925733850455027807451108123161768212073821382033500073069184011344280494573919716117539236653172

и т.д...

julia> ccall((:__gmpz_urandomm,:libgmp),Void,(Ptr{BigInt},Ptr{Uint8},Ptr{BigInt}),&x,buffer,&y)

джулия> х 5073599723113217446035606058203362324610326948685707674578205618189982426100515602680640230141018758328161278469759835943678360952795440512680380424413847653984694781421269745198616340362470820037933917709243387214511018480191308767310495781355601069937334945556566243556239048498564021992916827796124

person waTeim    schedule 26.07.2014

Это старый пост, но теперь Джулия позволяет легко решить этот вопрос.

Например, используя Julia 1.1.0 (я настроил свой REPL Julia для проекта, над которым я работаю, под названием JulieGo. Ответ должен работать так же, как и в обычном REPL Julia.)

JulieGo>VERSION
v"1.1.0"

# Set seed to get same results again.
JulieGo>rng_info = Random.seed!(12345);

# Here is an answer in Julia 1.1.0.    
JulieGo>r1 = rand(big"1":big"2"^1000)
8986172793045621030349078950793778042482316869955566599310906000510726536023373350273552788410494562
1437227128958537257991121543058284731429268230113459330352619981122924349300809967077942239392386680
0757367867423923215806277494619337596597641816501707643360907546040909561196900772512609868177829183

# Print result in an easy to read format.    
JulieGo>using Printf

JulieGo>@printf "%0.3E" float(r1)
8.986E+299

# Reseed the RNG.
JulieGo>rng_info = Random.seed!(12345);

# Try again.    
JulieGo>r2 = rand(big"1":big"2"^1000)
8986172793045621030349078950793778042482316869955566599310906000510726536023373350273552788410494562
1437227128958537257991121543058284731429268230113459330352619981122924349300809967077942239392386680
0757367867423923215806277494619337596597641816501707643360907546040909561196900772512609868177829183

# The result is the same.
JulieGo>@printf "%0.3E" float(r2)
8.986E+299

JulieGo>r1 == r2
true

# This also works.
# Reseed the RNG.
JulieGo>rng_info = Random.seed!(12345);

# Only the 2 needs to be specified explicitly as a big int.
JulieGo>r3 = rand(1:big"2"^1000)
898617279304562103034907895079377804248231686995556659931090600051072653602337335027355278841049456
143722712895853725799112154305828473142926823011345933035261998112292434930080996707794223939238668
075736786742392321580627749461933759659764181650170764336090754604090956119690077251260986817782918

JulieGo>r3 == r2
true
person Julia Learner    schedule 31.01.2019