Перейти к содержимому
  • 0
ArtHacker

Как получить случайное целое число?

Вопрос

Как получить рандомное число?

Просто math.random() в конце ещё .0 добавляет. Нам не нужно дробное число.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Рекомендуемые сообщения

2 часа назад, num_pi сказал:

function rand() local res = "" for i = 1, 8 do res = res .. string.char(math.random(48, 57)) end return tonumber(res) end

А зачем так сложно? В чём преимущество этого решения?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
11 минуту назад, eu_tomat сказал:

А зачем так сложно? В чём преимущество этого решения?

В том что оно работает =) Что конкретно тут сложно? Попробуй убрать string.char, посмотри что из этого получится. 

Изменено пользователем num_pi

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 минуту назад, num_pi сказал:

В том что оно работает =) Что конкретно тут сложно? Попробуй убрать string.char, посмотри что из этого получится. 

Конкретно тут math.random вызывается 8 раз. Разве не достаточно одного раза?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
Только что, eu_tomat сказал:

Конкретно тут math.random вызывается 8 раз. Разве не достаточно одного раза?

math.random(48, 57). Число 48 это unicode символ, а именно число 0, соответственно для числа 57, почти тоже самое, это число 9.

Получается что я, говорю math.random, дай мне рандомный unicode char, с 48 по 57, потом делаю конкатенацию  в for. Главное что работает, и делает именно то что просил человек.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
3 минуты назад, num_pi сказал:

Главное что работает, и делает именно то что просил человек.

Человек получил простое решение в первом же сообщении. Разумеется, можно придумать ещё сотню вариантов различной степени сложности. Но зачем?

 

Твой вариант имеет два недостатка: громоздкий код и повышенную нагрузку на сервер. Это может быть оправданным, если недостатки компенсируются каким-нибудь преимуществом. Поэтому возвращаемся к исходному вопросу:

36 минут назад, eu_tomat сказал:

В чём преимущество этого решения?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
4 часа назад, num_pi сказал:

res = res .. string.char(math.random(48, 57))

image.png.a93fa8dd49a240a1f6a8a0e3f03d70aa.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
5 часов назад, num_pi сказал:

 

Держи готовую функцию. for i = 1, 8 do: здесь поменяй 8, на большее число, если нужно что бы рандомное возвращаемое число было больше. 


function rand()
	local res = ""
	for i = 1, 8 do
		res = res .. string.char(math.random(48, 57))
	end
	return tonumber(res)
end

 

image.jpeg.67ed5806df2e87f9c7030108ef4cce69.jpeg
1) Магические числа - быдлокод. Что за 48 и 57? string.byte ('0'), string.byte ('9').
2) Результат будет всегда 8-значный или N-значный
3) math.floor??????
Ну и наконец, math.random возвращает целое число, если в него передать целое значение. math.random (10000000).
О производительности твоего примера я даже боюсь говорить. Вызов string.char в цикле, конкатенация строк, которые в луа иммутабельны просто убьют процессор, если функция будет использоваться часто.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, num_pi сказал:

. Главное что работает

Типичный сотрудник ubisoft:

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
В 14.01.2022 в 12:19, num_pi сказал:

Держи готовую функцию. for i = 1, 8 do: здесь поменяй 8, на большее число, если нужно что бы рандомное возвращаемое число было больше. 

Оставлю свои пять копеек для тех, кому нужно генерировать рандомные числа фиксированной длины. Хотя к теме это относится опосредованно, но мало ли:

-- Вариант 1
local function fixedLengthRandom(digits)
  digits = 10 ^ (digits - 1)
  return math.random(digits, digits * 10 - 1)
end

-- Вариант 2
local function fixedLengthRandom(digits)
  digits = 10 ^ (digits - 1)
  return math.floor(digits + math.random() * (digits - 1))
end

Вместо math.floor для ускорения процесса можно использовать операцию целочисленного деления // 1.0, однако она сохраняет нулевую дробную часть в результате и доступна только в Lua 5.3. На ваше усмотрение, короче. Результат:

>> fixedLengthRandom(4)
>> 4981

>> fixedLengthRandom(8)
>> 15896813

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, ECS сказал:

Вместо math.floor для ускорения процесса можно использовать операцию целочисленного деления // 1.0

А зачем здесь требуется math.floor?

В 22.11.2019 в 18:35, eu_tomat сказал:

math.random(lower, upper) генерирует целое число в диапазоне [lower..upper].

 

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, eu_tomat сказал:

А зачем здесь требуется math.floor

Прогнал, скопипастив из 2 примера. Спасибо, исправил

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
В 13.01.2022 в 21:34, eu_tomat сказал:

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

Получается как я понял, если использовать несколько раз команду print(math.random()) в компьютере из opencomputers, то получится один и тот же ответ? Или как?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
19 минут назад, Joe сказал:

Получается как я понял, если использовать несколько раз команду print(math.random()) в компьютере из opencomputers, то получится один и тот же ответ? Или как?

Нет. В этом случае получатся разные числа, хоть в цикле их запросишь, хоть без цикла, это не имеет значения. Об этом можно не волноваться.

 

Мои примеры должны были лишь продемонстрировать, что последовательности не случайны. И для этого я использовал стерильные условия. В OpenComputers же этой стерильности нет. Предсказуемость может возникнуть разве что по ошибке программиста, инициализирующего ГПСЧ при каждом запуске программы одинаковым значением. Разумеется, так делать не надо.

 

Но даже если инициализировать ГПСЧ текущим временем, то хакер, зная код программы, имеет шанс вычислить последовательность якобы случайных чисел, что позволит ему, например, выигрывать в неаккуратно написанных казино.

 

О, я совсем забыл поделиться своей радостью! Как хорошо, что эта тема, спустя два года, поднялась вновь.

С момента прошлого обсуждения я нашёл идеальный для OpenComputers источник энтропии. Вряд ли удастся найти лучший. Работает быстро и крайне непредсказуемо.

math.randomseed( -1e18*(os.clock()-os.clock()) )

Что ещё может быть более случайным в OpenComputers? Предлагайте свои варианты.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
1 час назад, eu_tomat сказал:

Предсказуемость может возникнуть разве что по ошибке программиста, инициализирующего ГПСЧ при каждом запуске программы одинаковым значением. Разумеется, так делать не надо.

Это как при написание рандомайзера на плате arduino, и при компиляции код замкнуть один из цифровых контактов, числа всегда будут одинаковы.

 

1 час назад, eu_tomat сказал:

Но даже если инициализировать ГПСЧ текущим временем, то хакер, зная код программы, имеет шанс вычислить последовательность якобы случайных чисел, что позволит ему, например, выигрывать в неаккуратно написанных казино.

Я подозреваю, что на этапе получения кода, у хакера появятся сложности.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
12 часа назад, eu_tomat сказал:

math.randomseed( -1e18*(os.clock()-os.clock()) )

Идея с clock хорошая, но будет работать только в рамках мода из-за хука на вызовы функций в machine.lua. А как ты выбрал магическую константу? Это явно не math.mininteger/maxinteger, а что-то чернокнижное

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
В 14.01.2022 в 16:49, ECS сказал:

Оставлю свои пять копеек для тех, кому нужно генерировать рандомные числа фиксированной длины. Хотя к теме это относится опосредованно, но мало ли:


-- Вариант 1
local function fixedLengthRandom(digits)
  digits = 10 ^ (digits - 1)
  return math.random(digits, digits * 10)
end

-- Вариант 2
local function fixedLengthRandom(digits)
  digits = 10 ^ digits
  return math.floor(digits + math.random() * (digits - 1))
end

 

Только они чутка бракованные. В первом варианте поскольку рандом с границами генерирует включительно, иногда генерирует на 1 цифру больше, т. е. [1; 10], [10; 100] и т. д. А во втором варианте оно вообще фигню делает, [10; 18], [100; 198] и т. д.

Ну и чутка бессмысленный момент: 0 это число длины 1, а должна ли функция его генерировать?

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
2 часа назад, astral17 сказал:

Только они чутка бракованные

Черт, стыдно стало, поправил диапазон :d

 

2 часа назад, astral17 сказал:

 0 это число длины 1, а должна ли функция его генерировать?

А тут начинается le classique, то есть выбор между производительностью и охватом всех вероятных условий и ошибок. По ТЗ, формируемому названием функции, - да, должна, а ещё ей по-хорошему не хватает парочки валидаций.

 

Начнем с того, что количество цифр в генерируемом числе не должно быть < 1, ибо таких чисел не существует. Также оно не может быть больше 18 для 64-битного бинарника Lua, т.к. именно 18 является максимально допустимой степенью показательной функции f(x) = 10 ^ x, значение которой не превышает рабочий диапазон. Пруф:

math.log(math.maxinteger, 10)
> 18.964889726831

math.random(10 ^ 18)
> 902800305889519796

math.random(10 ^ 19)
> stdin:1: bad argument #1 to 'random' (number has no integer representation)

И наконец, можно добавить поддержку генерации нуля в крайне странном случае, когда кто-то решил воспользоваться нашей функцией вместо math.random(0, 9):

local function fixedLengthRandom(digits)
  assert(digits >= 1 and digits <= 18, "Digit count is out of range [1; 18]")
  
  if digits == 1 then
    return math.random(0, 9)
  end
  
  digits = 10 ^ (digits - 1)
  
  return math.random(digits, digits * 10 - 1)
end

Это что касается решения "по бумажкам в лабораторных условиях". На практике же оно на фиг никому не упало, и куда предпочтительнее был бы производительный вариант без избыточных проверок, которые имеют свой бюджет вызовов в опенкомпах. Так что же правильнее? Наверное, то, что лично ты считаешь правильным для конкретной ситуации

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
4 часа назад, ECS сказал:

Идея с clock хорошая, но будет работать только в рамках мода из-за хука на вызовы функций в machine.lua.

А разве нам требуется что-то кроме этого? Во взрослых средах имеются более адекватные источники энтропии. А в среде OpenComputers приходится импровизировать.

 

7 часов назад, ECS сказал:

 А как ты выбрал магическую константу? Это явно не math.mininteger/maxinteger, а что-то чернокнижное

Это значение выбрано на глаз. На шаманский глаз. Достаточно было бы и math.pow(2,52), чтобы перевести в целую часть все разряды мантиссы.

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах
12 часа назад, eu_tomat сказал:

А разве нам требуется что-то кроме этого? Во взрослых средах имеются более адекватные источники энтропии. А в среде OpenComputers приходится импровизировать

Нет, для мода, конечно, не требуется. Я на всякий случай подчеркнул этот момент - вдруг какая-то заблудшая душа будет искать ответ и не поймет, какого ж черта os.clock() - os.clock() может выдавать что-то, отличное от нуля. И будет плакать...

 

12 часа назад, eu_tomat сказал:

Достаточно было бы и math.pow(2,52), чтобы перевести в целую часть все разряды мантиссы

А, вон какая логика была. Занятно, спасибо

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

А почему os.clock() - os.clock() случайное?

Первый вызов начинает выполняться в  момент t1, какое-то время выполняется и возвращает значение T1 между t1 и t2

Второй вызов начинает выполняться в  момент t2, какое-то время выполняется и возвращает значение T2 между t2 и t3

Какие значения тут случайны? Длительность выполнения os.clock()? Возвращаемые им значения?(в пределах длительности)

image.png.45ccc9dc08f5717cd8679d998b61ae24.png

Поделиться сообщением


Ссылка на сообщение
Поделиться на других сайтах

Присоединяйтесь к обсуждению

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

Гость
Ответить на вопрос...

×   Вы вставили отформатированное содержимое.   Удалить форматирование

  Разрешено использовать не более 75 эмодзи.

×   Ваша ссылка была автоматически встроена.   Отобразить как ссылку

×   Ваш предыдущий контент был восстановлен.   Очистить редактор

×   Вы не можете вставлять изображения напрямую. Загружайте или вставляйте изображения по ссылке.


×
×
  • Создать...