Подтвердить что ты не робот

Генерировать случайное число от 0,1 до 1,0. питон

Я пытаюсь создать случайное число от 0,1 до 1,0. Мы не можем использовать rand.randint, потому что он возвращает целые числа. Мы также попробовали random.uniform(0.1,1.0), но он возвращает значение >= 0,1 и < 1.0, мы не можем использовать это, потому что наш поиск включает также 1.0.

У кого-то еще есть идея для этой проблемы?

4b9b3361

Ответ 1

Как "точные" вам нужны ваши случайные числа? Если вы довольны, скажем, 10 десятичными знаками, вы можете просто округлить random.uniform(0.1, 1.0) до 10 цифр. Таким образом вы будете включать как 0.1, так и 1.0:

round(random.uniform(0.1, 1.0), 10)

Если быть точным, 0.1 и 1.0 будут иметь только половину вероятности по сравнению с любым другим числом между ними, и, конечно же, вы потеряете все случайные числа, которые отличаются только после 10 цифр.

Ответ 2

Random.uniform() просто:

def uniform(self, a, b):
    "Get a random number in the range [a, b) or [a, b] depending on rounding."
    return a + (b-a) * self.random()

где self.random() возвращает случайное число в диапазоне [0.0, 1.0).

Python (как и многие другие языки) использует плавающий точка, чтобы представлять реальную номера. Как представлен 0.1, подробно описан в документы:

from __future__ import division

BPF = 53 # assume IEEE 754 double-precision binary floating-point format
N = BPF + 3
assert 0.1 == 7205759403792794 / 2 ** N

Это позволяет найти случайное число в [0.1, 1] (включительно), используя randint() без потери точности:

n, m = 7205759403792794, 2 ** N
f = randint(n, m) / m

randint(n, m) возвращает случайное целое число в [n, m] (включительно) поэтому вышеупомянутый метод может потенциально возвращать все плавающие точки числа в [0.1, 1].

Альтернативой является найти наименьший x такой, что x > 1 и использовать:

f = uniform(.1, x)
while f > 1:
    f = uniform(.1, x)

x должно быть наименьшим значением, чтобы избежать потери точности и уменьшите количество вызовов до uniform() например:

import sys
# from itertools import count

# decimal.Decimal(1).next_plus() analog
# x = next(x for i in count(1) for x in [(2**BPF + i) / 2**BPF] if x > 1)
x = 1 + sys.float_info.epsilon

Оба решения сохраняют равномерность случайного распределения (нет перекоса).

Ответ 3

Вы можете сделать это:

>>> import numpy as np
>>> a=.1
>>> b=np.nextafter(1,2)
>>> print(b)
1.0000000000000002
>>> [a+(b-a)*random.random() for i in range(10)]

или, используйте numpy uniform:

np.random.uniform(low=0.1, high=np.nextafter(1,2), size=1)

nextafter создаст конкретное для платформы следующее отображаемое число с плавающей запятой в направлении. Использование numpy random.uniform выгодно, потому что недвусмысленно, что оно не включает верхнюю границу.


Изменить

Похоже, что комментарии Марка Дикинсона верны: Документация по номеру неверна в отношении верхней границы к random.uniform включительно или нет.

Документация Numpy содержит All values generated will be less than high.

Это легко опровергнуть:

>>> low=1.0
>>> high=1.0+2**-49
>>> a=np.random.uniform(low=low, high=high, size=10000)
>>> len(np.where(a==high)[0])
640

В этом ограниченном диапазоне результат равен единице:

>>> for e in sorted(set(a)):
...    print('{:.16e}: {}'.format(e,len(np.where(a==e)[0])))
... 
1.0000000000000000e+00: 652
1.0000000000000002e+00: 1215
1.0000000000000004e+00: 1249
1.0000000000000007e+00: 1288
1.0000000000000009e+00: 1245
1.0000000000000011e+00: 1241
1.0000000000000013e+00: 1228
1.0000000000000016e+00: 1242
1.0000000000000018e+00: 640

Однако, комментируя комментарии Ю. Ф. Себастьяна и Марка Дикинсона, я думаю, что это работает:

import numpy as np
import random 

def rand_range(low=0,high=1,size=1):
    a=np.nextafter(low,float('-inf'))
    b=np.nextafter(high,float('inf'))
    def r():
        def rn(): 
            return a+(b-a)*random.random()

        _rtr=rn()
        while  _rtr > high:
            _rtr=rn()
        if _rtr<low: 
            _rtr=low
        return _rtr     
    return [r() for i in range(size)]

Если вы запускаете с минимальным разбросом значений в комментарии Mark, чтобы было очень мало отдельных значений с плавающей запятой:

l,h=1,1+2**-48
s=10000
rands=rand_range(l,h,s)    
se=sorted(set(rands))
if len(se)<25:
    for i,e in enumerate(se,1):
        c=rands.count(e)
        note=''
        if e==l: note='low value end point'
        if e==h: note='high value end point'
        print ('{:>2} {:.16e} {:,}, {:.4%} {}'.format(i, e, c, c/s,note))

Получает желаемое равномерное распределение, включая конечные точки:

 1 1.0000000000000000e+00 589, 5.8900% low value end point
 2 1.0000000000000002e+00 544, 5.4400% 
 3 1.0000000000000004e+00 612, 6.1200% 
 4 1.0000000000000007e+00 569, 5.6900% 
 5 1.0000000000000009e+00 593, 5.9300% 
 6 1.0000000000000011e+00 580, 5.8000% 
 7 1.0000000000000013e+00 565, 5.6500% 
 8 1.0000000000000016e+00 584, 5.8400% 
 9 1.0000000000000018e+00 603, 6.0300% 
10 1.0000000000000020e+00 589, 5.8900% 
11 1.0000000000000022e+00 597, 5.9700% 
12 1.0000000000000024e+00 591, 5.9100% 
13 1.0000000000000027e+00 572, 5.7200% 
14 1.0000000000000029e+00 619, 6.1900% 
15 1.0000000000000031e+00 593, 5.9300% 
16 1.0000000000000033e+00 592, 5.9200% 
17 1.0000000000000036e+00 608, 6.0800% high value end point

В отношении значений, запрошенных OP, он также создает равномерное распределение:

import matplotlib.pyplot as plt

l,h=.1,1  
s=10000
bin_count=20
rands=rand_range(l,h,s)  
count, bins, ignored = plt.hist(np.array(rands),bin_count)   
plt.plot(bins, np.ones_like(bins)*s/bin_count, linewidth=2, color='r')
plt.show()   

Выход

uniform

Ответ 4

С информацией, которую вы предоставили (включая комментарии до сих пор), я все еще не понимаю, как университет собирается протестировать вашу программу, так что будет иметь значение, если появится 1.0 или нет. (Я имею в виду, если вам нужно создавать случайные поплавки, как они могут потребовать, чтобы появилось какое-то определенное значение?)

ОК, поэтому отбросьте сумасшествие ваших требований:

Тот факт, что нижняя граница ваших случайных поплавков выше 0, дает вам изящно элегантный способ использования random.random, который гарантирует возвращаемые значения в интервале [0.0, 1.0]: просто продолжайте звонить random.random, бросая от любых значений менее 0,1, кроме 0,0. Если вы действительно получаете 0.0, верните 1.0 вместо этого.

Так что-то вроде

from random import random

def myRandom():
    while True:
        r = random()
        if r >= 0.1:
            return r
        if r == 0.0:
            return 1.0

Ответ 5

Вы можете использовать random.randint просто, выполнив этот трюк:

>>> float(random.randint(1000,10000)) / 10000
0.4362

если вы хотите больше десятичных знаков, просто измените интервал на:

(1000 10000) 4 цифры (10000 100 000) 5 цифр и т.д.

Ответ 6

Вы не можете использовать random.random()? Это дает число от 0.0 до 1.0, хотя вы можете легко настроить способ обойти это.

import random
def randomForMe():
    number = random.random()
    number = round(number, 1)
    if (number == 0):
        number = 0.1

Этот код даст вам число от 0,1 до 1,0 включительно (0,1 и 1,0 - оба возможных решения). Надеюсь, это поможет.

* Я предположил, что вы только хотели числа на десятое место. Если вы хотите, чтобы он был другим, где я набрал round(number, 1), измените 1 на 2 на сотые, 3 на тысячные и т.д.

Ответ 7

Стандартным способом было бы random.random() * 0.9 + 0.1 (random.uniform() внутренне делает именно это). Это вернет числа от 0,1 до 1,0 без верхней границы.

Но подождите! 0.1 (aka ¹/₁₀) не имеет четкого двоичного представления (как ⅓ в десятичной форме)! Таким образом, вы все равно не получите истинный 0,1, просто потому, что компьютер не может представлять его внутренне. Извините; -)

Ответ 8

Согласно документации Python 3.0 :

random. равномерное (a, b) Возвращает случайное число N с плавающей запятой, такое, что a <= N <= b для a <= b и b <= N <= a для b < а.

Таким образом, random.uniform() действительно включает верхний предел, по крайней мере, на Python 3.0.

EDIT: Как указано в @Blender, документация для Python 3.0, по-видимому, несовместима с исходным кодом в этой точке.

EDIT 2: Как отметил @MarkDickinson, я непреднамеренно связал с документацией Python 3.0, а не последнюю документацию Python 3 здесь, которая читается следующим образом:

случайный. единообразный (a, b) Возвращает случайное число с плавающей запятой N такое что a <= N <= b дл <= b и b <= N <= a для b < а.

Конечная точка значение b может или не может быть включено в диапазон в зависимости от округление с плавающей запятой в уравнении a + (b-a) * random().

Ответ 9

Try   random.randint(1, 10)/100.0