Tehnografi.com - Технологические новости, обзоры и советы

Случайные числа в Swift

Следующая статья поможет вам: Случайные числа в Swift

Вернуться в блог

Давайте посмотрим на случайность и случайные числа в Swift. Swift имеет ряд встроенных функций, которые помогают генерировать случайные числа, но с некоторыми оговорками!

Но сначала… зачем вам случайные числа в Swift?

  • В игровых приложениях вы используете случайные числа для имитации бросков кубиков или даже имитируете «хаос» и непредсказуемость в своих играх, например, случайные позиции врагов или случайное появление обновлений.
  • В практической разработке для iOS вы используете случайность, чтобы выбрать случайный элемент из массива.
  • При создании объекта или нового пользователя иногда требуется случайный уникальный идентификатор.

В Свифте 4.2. и выше, изменился способ работы со случайными числами. Вместо использования импортированной функции C arc4random() теперь вы можете использовать собственные функции Swift.

Давайте посмотрим на пример:

пусть число = Int.random(in: 0..<10)
В приведенном выше примере генерируется случайное целое число от 0 до 10. Используется оператор полуоткрытого диапазона ..<, и результатом является диапазон от 0 до 10, не включая 10.
Вы также можете использовать оператор замкнутого диапазона…, чтобы получить случайное целое число от 0 до 10, включая 10. Вот так:

пусть число = Int.random(входное: 0…10)

Вы можете использовать функцию random(in:) для получения случайных значений для нескольких примитивных типов, таких как Int, Double, Float и даже Bool. Так:

пусть дробь = Float.random(in: 0..<1)
Приведенный выше пример возвращает случайное значение с плавающей запятой, то есть число с дробью от 0 до 1.

А приведенный ниже пример возвращает true или false – случайное логическое значение! Они очень полезны для случайного тестирования условной логики.

пусть StayOrGo = Bool.random()
А как насчет выбора случайного элемента из массива? Вы можете сделать это следующим образом:

пусть имена = [“Ford”, “Zaphod”, “Trillian”, “Arthur”, “Marvin”]
пусть случайное имя = имена.randomElement()

В приведенном выше коде вы используете randomElement() для массива имен. Вы можете использовать эту функцию в любой коллекции, например в массивах и словарях. Имейте в виду, что возвращаемый случайный элемент является необязательным.

Можете ли вы также использовать новые случайные функции в Swift 4.2. перетасовать массив? Да! Рандомизировать порядок массива на удивление просто:

имена вар = [“Ford”, “Zaphod”, “Trillian”, “Arthur”, “Marvin”]
имена.shuffle()
// `names` теперь могут быть: [“Zaphod”, “Marvin”, “Arthur”, “Ford”, “Trillian”]

Функции перемешивания используют типичную структуру именования Swift, поэтому shuffle() перемешивает массив на месте, изменяя исходный массив, а shuffled() возвращает копию перетасованного массива.

Вы даже можете перетасовать последовательность, вот так:

let последовательность = 0 ..< 7 let shuffledSequence = последовательность.shuffled() // `shuffledSequence` теперь может быть: [0, 6, 2, 3, 4, 1, 5]
Просто, правда? Гораздо проще, чем arc4random_uniform(_:) до версии 4.2 со всем этим приведением типов…

Вы используете версию Swift ниже 4.2? Затем используйте функции случайных чисел, описанные в главах ниже.

Swift имеет три типичные функции для случайных чисел:

arc4random() возвращает случайное число от 0 до 232–1.
arc4random_uniform(_:) возвращает случайное число от нуля до первого параметра минус один.
drand48() возвращает случайное число Double от 0,0 до 1,0.
И arc4random(), и arc4random_uniform(_:) используют тип UInt32 вместо более типичного Int.

Рекомендуется использовать arc4random_uniform(_:) вместо arc4random(), поскольку последний страдает от условия, называемого «смещение по модулю». Это приводит к тому, что определенные числа появляются чаще, чем другие, что подрывает «случайность» функции.

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

Интересный факт: ранние компьютеры, и особенно компьютерные игры, содержали файл со случайными числами. Программа будет последовательно выбирать случайные числа из этого файла всякий раз, когда ей нужно случайное число, вместо того, чтобы вычислять случайное число самостоятельно!

В наши дни механизм не сильно отличается, хотя iOS или Android имеют большой запас случайно сгенерированных чисел. Вычисление большого набора случайных чисел перед его использованием называется засевом.

Функция arc4random_uniform(_:) принимает один параметр — верхнюю границу. Он вернет случайное число от 0 до этой верхней границы минус 1.

Так:

arc4random_uniform(42)
// Вывод: 13
Это вернет случайное число от 0 до 41. Результат имеет тип UInt32, поэтому, если вы хотите работать с обычным целым числом в своем коде, вам придется преобразовать или привести его к Int.

Так:

пусть n = Int(arc4random_uniform(42))
Константа n теперь имеет тип Int, с которым легче работать.

А как насчет двойников? Как вы знаете, дабл — это число с десятичной точкой и двойной точностью. Чаще всего он используется в Swift для чисел, содержащих запятые или дроби.

Вот как вы генерируете случайное двойное число в Swift от 0,0 до 1,0:

пусть d = drand48()
распечатать(д)
// Вывод: 0,396464773760275
Аккуратный!

Краткое примечание: у всех компьютеров есть проблемы с представлением чисел и дробей с плавающей запятой, поэтому логически функция drand48() работает, просто помещая пару целых чисел друг за другом…

Теперь с этой функцией arc4random_uniform(_:) работать немного странно. Давайте напишем удобную функцию, которая поможет вам работать со случайными числами.

Так:

func random(_ n:Int) -> Int {
вернуть Int(arc4random_uniform(UInt32(n)))
}
Эта функция принимает безымянный параметр n типа Int и возвращает целое число от 0 до n-1. Как видите, внутри вызова arc4random_uniform(_:) n преобразуется в UInt32, а возвращаемое значение arc4random_uniform(_:) преобразуется обратно в Int.

Если вы используете Swift 4.2. или выше, вам не понадобятся эти удобные функции. Просто используйте .random() или .randomElement(), как описано в главах выше.

Далее вы можете сгенерировать несколько случайных чисел следующим образом:

для меня в 0…100 {
печать (случайное (100))
}
Это выведет 100 случайных чисел от 0 до 99.

В Swift есть оператор полуоткрытого диапазона, например 0..<42. Почему бы вам не использовать его для изменения функции удобства? Вот так: func random(_ range:Range) -> Int
{
return range.lowerBound + Int(arc4random_uniform(UInt32(range.upperBound – range.lowerBound)))
}

Вместо одного входного числа эта функция принимает диапазон, например 0..<42, и возвращает число от 0 до 42, не включая 42.
Внутри функции результат сначала добавляется к нижней границе диапазона, гарантируя, что случайное число всегда начинается с этой нижней границы. Внутри функции arc4random_uniform(_:) нижняя граница вычитается из верхней границы, так что возвращаемый результат аккуратно лежит между нижней и верхней границей.

Эта функция намеренно использует универсальный тип Range с полуоткрытым диапазоном вместо общего типа ClosedRange с закрытым диапазоном, поскольку он лучше отражает диапазон результирующих чисел из arc4random_uniform(_:).

Вы можете использовать функцию случайного числа из диапазона следующим образом:

для меня в 0…100 {
печать(случайное(1..<42)) }
Это выведет 100 случайных чисел от 1 до 41.

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

Как вы знаете, функция arc4random_uniform(_:) возвращает целое число от нуля до верхней границы. Если мы используем array.count в качестве верхней границы, функция вернет порядковый номер в пределах массива!

Так:

пусть имена = [“Arthur”, “Ford”, “Zaphod”, “Marvin”, “Trillian”]

пусть случайные = имена[Int(arc4random_uniform(UInt32(names.count)))]
печать (случайная)
// Вывод: Марвин
В этом примере создается случайное число между нулем и именами.count, которое используется для получения значения из массива имен с синтаксисом индексов.

Вы можете удобно превратить приведенный выше пример в расширение для Array, например:

расширение Массив
{
func random() -> Элемент {
вернуть себя[Int(arc4random_uniform(UInt32(self.count)))]
}
}
Точно так же, как и раньше, возвращается случайный элемент массива. В приведенном выше примере Element относится к псевдониму типа элемента в массиве, а self относится к текущему экземпляру массива.

Вы можете использовать его следующим образом:

пусть имена = [“Arthur”, “Ford”, “Zaphod”, “Marvin”, “Trillian”]
печать(names.random())
// Вывод: Триллиан
А как насчет перетасовки массива? Посмотрите этот урок: Перетасовка массивов в Swift с помощью Fisher-Yates

Что делать, если вы хотите сгенерировать случайную строку? Вы можете сделать это следующим образом:

func randomString(_ n: Int) -> String
{
let digits = «abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890»
вар результат = «»

для _ в 0.. Строка {
let digits = «abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ1234567890»
вернуть строку (массив (0..

  • Строки в Swift могут быть немного сложными… Подробнее о них можно прочитать здесь:
  • Не используйте эти функции для генерации случайных паролей — они недостаточно надежны. Используйте менеджер паролей, например Последний проход вместо.
  • Будьте осторожны при создании случайных идентификаторов или ключей для вашей базы данных, поскольку легко создать коллизию. Лучше использовать уникальный генератор строк, например UUID.
  • Потрясающий! Мы сгенерировали целую кучу случайных вещей. Вот что мы обсуждали: