Swift与随机数:可预测的魔法
\n\n每位开发者迟早都会遇到这样一个问题:“如何生成一个随机数?”看起来很简单,对吧?但在Swift的世界里,这个话题经历了一段漫长的演变——从古老的C语言函数到优雅的内置API。在本文中,我们将探讨Swift中生成随机数的所有方法,从简单到工业级,附带实际示例和重要细节。
\n\n如果你曾经疑惑为什么你的arc4random()会返回奇怪的数字,或者如何从数组中真正随机选择一个元素——那你来对地方了。我们开始吧!
简史:我们是如何走到这一步的
\n\n在Swift 4.2(2018年)之前,开发者们痛苦地在arc4random()、drand48()和像rand() % 100这样的临时方案之间做选择。顺便说一句,后者很危险——如果范围不能被RAND_MAX整除,分布偏差(bias)是必然的。随着Swift 4.2的发布,Apple为我们带来了RandomNumberGenerator协议和内置方法。现在,随机数生成变得安全、可读且统一。
现代方法:RandomNumberGenerator和类型方法
\n\n从Swift 4.2开始,最正确且最简单的方法是使用类型上的静态方法:
\n\n// 从1到100的随机整数\nlet randomInt = Int.random(in: 1...100)\n\n// 从0.0到1.0的随机浮点数\nlet randomDouble = Double.random(in: 0.0...1.0)\n\n// 随机Float\nlet randomFloat = Float.random(in: 0.0...1.0)\n\n// 随机Bool\nlet randomBool = Bool.random()\n\n\n这个API使用系统生成器SystemRandomNumberGenerator,它是加密安全的(稍后会详细说明)。重要:范围通过闭区间(...)或半开区间(..<)指定。
为什么这很酷?
\n- \n
- 类型安全——编译器不会让你生成一个Double却赋值给Int。 \n
- 无偏差——Swift自动确保均匀分布。 \n
- 通用性——适用于所有数值类型:Int、UInt、Int8、Float、Double、CGFloat甚至Bool。 \n
从范围生成随机数:常见陷阱
\n\n看起来,能出什么问题呢?来看一个例子:
\n\nlet diceRoll = Int.random(in: 1...6) // 骰子:1,2,3,4,5,6\nlet coinFlip = Int.random(in: 0..<2) // 硬币:0或1\n\n\n一切正常。但如果你想生成一个没有上限的随机数(例如,从0到无穷大)——那是不行的。Swift要求明确指定范围。这是特意设计的,以避免溢出错误。
\n\n如果你需要一个从0到max(其中max是一个变量)的随机数,只需使用:
let maxValue = 500\nlet randomUpTo = Int.random(in: 0...maxValue)\n\n\n从集合中随机选取元素(Array、Set、Dictionary)
\n\n生成随机数本身往往不是目的,而是为了选择一个随机元素。Swift提供了一个优雅的解决方案:
\n\nlet fruits = ["苹果", "香蕉", "樱桃", "甜瓜"]\nif let randomFruit = fruits.randomElement() {\n print("今天吃 \\(randomFruit)")\n} else {\n print("篮子空了!")\n}\n\n\nrandomElement()方法返回一个可选值——这很重要,因为集合可能为空。要打乱整个数组,请使用shuffled():
let shuffledFruits = fruits.shuffled()\nprint(shuffledFruits) // 例如:["香蕉", "甜瓜", "苹果", "樱桃"]\n\n\n加密安全生成:当安全高于一切
\n\n标准的I