Калькулятор случайных сумм

Я пытаюсь вычислить случайную сумму, но, например, по редкости:

choices = [10,100,1000,10000]

10 является наиболее распространенным, 100 более распространенным, 1000 редко и 10000 чрезвычайно редко.

Я пробовал это

import random
def getAmmounts():
    choices = [10, 100, 1000, 10000]
    values = [random.choice(choices) for i in range(10)]
    return values

Которая возвращает хорошее количество значений, но они не такие случайные 10000 появляется довольно часто, когда почти никогда не должно появляться, когда я вызвал на него данные, которые я получил:

[1000, 10000, 100, 1000, 10000, 10, 1000, 10000, 100, 100]

Здесь два 10000's и почти нет значений 10, когда 10s и 100s должны быть наиболее распространенными, чем случайные 1000 в миксе, но почти никогда не имеют значения 10000. Есть ли способ настроить для этого функцию типа приоритета? Вот несколько хороших примеров данных о том, что это должно возвращать после того, как все сказано в готовом:

[10,10,100,10,10,100,1000]

И иногда 10000, но это должно быть очень редко, есть идеи, как это настроить?


person user2925490    schedule 18.11.2013    source источник
comment
Насколько часто (то есть с какой вероятностью) должно быть каждое число?   -  person jwodder    schedule 18.11.2013
comment
@jwodder вероятность каждого из них не является точной величиной, но 10s должна быть наиболее распространенной, поэтому данные с 20 значениями 10 должны появляться примерно 6-10 раз, но никогда не точны до 100-го значения, вероятно, 3-5 тысяч один или два раза, но почти никогда появление значения 10000   -  person user2925490    schedule 19.11.2013
comment
@ user2925490 То, что спрашивает jwodder, на самом деле является намеком на всеобъемлющее решение. Вы хотите присвоить вероятность этим значениям, где, скажем, 10 появляется в 80% случаев, 100 появляется в 10% случаев, 1000 появляется в 8% случаев, а 10000 появляется в 2% случаев. Однако при назначении этому фактическому процентному соотношению имейте в виду, сколько раз getAmounts() будет выполняться в реальном времени, так что, если пользователь может запускать getAmounts() 1000 раз в минуту в соответствии с вашей реализацией этого, вы все равно будете иметь 10000 редкое число. (один или два раза). Для этого потребуется математика проб / статистики.   -  person jwarner112    schedule 19.11.2013
comment
Также дубликат этого, это, это, this, this и, вероятно, десятки других вопросов.   -  person abarnert    schedule 19.11.2013
comment
@ user2925490 В дополнение к тому, что я только что сказал, вы сказали, что хотите, чтобы 10 появился 6 out of 20 times. Изменив это на статистическую проблему, обратите внимание, что 6 of 20 может быть выражено в процентах ((6/20)*100 = 30%!)   -  person jwarner112    schedule 19.11.2013


Ответы (6)


Ваш код не присваивает вероятностей. Вы можете рассчитывать, что 10 будет менее редким, чем 10000, но Python этого не узнает.

Вы можете смоделировать вероятность, используя random.random, чтобы сгенерировать случайное число от 0 до 1 и вернуть соответствующее число в зависимости от сгенерированного числа.

Например

import random

def make_number():
  val = random.random()
  if val < 0.1: #10%
    return 10000
  elif val < 0.3: # 20%
    return 1000
  elif val < 0.6: # 30%
    return 100
  else: # 40%
    return 10

values = [make_number() for i in range(10)]
print (values)
person MxLDevs    schedule 18.11.2013
comment
Это хорошо, но будьте осторожны с логикой здесь, когда будете ее реализовывать, OP. Если вы измените знак оператора, вы можете столкнуться с проблемами из-за составной структуры elif. Например, вы не можете переставить знаки на >, иначе возникнут проблемы. - person jwarner112; 19.11.2013
comment
После написания его также было довольно сложно поддерживать. Я бы использовал хеш для хранения вероятностей, которые было бы намного проще поддерживать. Или что-то чистое, например ответ в этом вопросе, поскольку вы можете легко добавлять или удалять случаи. - person MxLDevs; 19.11.2013
comment
@Keikoku Немного изменил его, и он отлично работал, и благодаря всем остальным, которые дали ответ, все они помогли, когда я модифицировал его в соответствии со своими потребностями. - person user2925490; 19.11.2013

Входной список получает равную вероятность для каждого элемента. Подайте ему список с нужными вам пропорциями.

choices = [10, 10, 10, 100]

будет 10 в три раза больше, чем 100.

person tripleee    schedule 18.11.2013
comment
Ручная настройка вероятности, подобная этой, - хороший способ начать, но я получаю беспорядок, когда масштаб реализации хоть немного увеличивается. В долгосрочной перспективе более полезно изучить вероятность / статистику (очень простые версии), чтобы понять, как заставить компьютер генерировать пропорционально для вас. - person jwarner112; 19.11.2013

Почему бы вам не сгенерировать число, а затем назначить его на основе диапазона:

x = randint(1,11)
if x == 10:
    #This is the rarest, occurring only 10% of the time
elif x < 10 and x >= 8:
    #9 or 8 aka 20%
elif x < 8 and x >= 5:
    #7, 6, 5 aka 30%

Вы можете настроить его как хотите или увеличить диапазон, чтобы получить более конкретные шансы.

person Tyler    schedule 18.11.2013
comment
Это решение более элегантно, чем у Джуда или тройки, потому что там, где вы вручную добавляете записи с желаемой вероятностью, здесь используется диапазон, чтобы сделать это за вас. Это не так элегантно, как прямая реализация, но я бы предпочел это всему, что я видел. - person jwarner112; 19.11.2013
comment
Если я правильно понимаю, первая часть каждой строки elif является лишней, так как elif не просматривается, если if / elif выше его истинно. Итак, if x == 10, elif x >= 8, elif x >= 5, else Я прав? - person Ernesto; 19.11.2013

Вы можете произвести случайное число

import random
x = random.random() % this produces a random number between 0 and 1

и вы можете использовать случайно сгенерированное число, чтобы выбрать между 10, 100, 1000 и 10000:

if x < 0.5:        # x is between 0 and .50, so 50% chance
    choice = 10
else if x < 0.75:  # x is between .50 and .75, so 75-50 = 25% chance
    choice = 100
else if x < 0.9:   # x is between .75 and .90, so 90-75 = 15% chance
    choice = 1000
else:
    choice = 10000 # x is between .90 and 1, so 100-90 = 10% chance (5 times less likely than the first one)

это выводит 10 на 50% запусков, 100 на 25% запусков, 1000 на 15% запусков и 10000 на 10% запусков. Вы можете настроить диапазоны для любого распределения по вашему желанию [10,100,1000,10000]!

person arturomp    schedule 18.11.2013
comment
Никогда не думал об использовании для этого случайного десятичного числа, сейчас я хочу отредактировать свой ответ, чтобы использовать его, но я не хочу красть вашу идею;) Мне нравится использование списка, а не прямое присвоение значения , поскольку вам придется изменить код, если вы хотите изменить значения, если вы не используете список значений. - person Ernesto; 19.11.2013

Быстрое (хотя и не обязательно лучшее) решение - наклеить несколько копий чисел, которые вы хотите чаще отображать в списке:

import random
def getAmmounts():
    choices = [10] * 80 + [100] * 15 + [1000] * 4 + [10000] * 1
    values = [random.choice(choices) for i in range(10)]
    return values
person Jud    schedule 18.11.2013
comment
Технически это решение, но действительно беспорядочное, которое не может масштабироваться ни в одном приложении. Гораздо полезнее потратить время на изучение ответа, основанного на статистике. - person jwarner112; 19.11.2013
comment
Отсюда и мой быстрый, но не лучший. Я не знаю, насколько гибкое решение нужно OP. - person Jud; 19.11.2013
comment
Совершенно верно, я просматриваю их все, чтобы увидеть, насколько близко к прямой реализации мы можем заставить OP использовать; чем прямее, тем (сложнее), наверное, будет лучше. - person jwarner112; 19.11.2013

import random

def getAmounts():
  amount = random.random(1,10)
  if amount == 10:
    return 10000
  elif amount > 8:
    return 1000
  elif amount > 5:
    return 100
  else:
    return 10

Или, если вы хотите использовать список, вы можете сделать что-то вроде (у меня нет открытого IDLE, и он долго загружается, поэтому, если я немного отключился, я прошу прощения.)

import random

def getAmounts():
    values = [10, 100, 1000, 10000]
    amount = random.random(1,10)
    if amount == 10:
        return values[3]
    elif amount > 8:
        return values[2]
    elif amount > 5:
    return values [1]
  else:
    return values[0]

Используя списки, вы всегда можете изменить фактические значения, которые вы возвращаете, поэтому, если вместо 10, 100, 1000, 10000 вы хотите вернуть 50, 500, 5000 и 50000, вы можете просто переназначить список значений, и код по-прежнему работает , без необходимости проходить и менять каждую строку.

person Ernesto    schedule 18.11.2013