Swift对象随机数引用异常:训练计划次数重复出现低数值问题
搞定你的随机训练计划Bug!
看起来你遇到的问题是随机生成的训练次数(reps)分布完全不符合预期——大部分是1、2,偶尔蹦出个14,这肯定是随机数生成逻辑出问题了,咱们一步步来解决:
问题到底出在哪?
从你贴的代码片段看,核心问题在arc4rand...的用法上。我猜你大概率是直接把arc4random()转成Int,或者用了错误的取模方式,导致随机数的范围和分布完全跑偏了。
比如这种错误写法:
// 错误示范:直接转Int后取模,会因为UInt32转Int的溢出问题,导致结果集中在小数值 reps: Int(arc4random()) % 15
或者你可能不小心把随机范围设成了1-2,偶尔因为数值溢出才出现14这种异常值。
正确生成训练次数的姿势
要生成均匀分布的合理训练次数(比如常见的8-15次),推荐用arc4random_uniform(_:),它专门用来生成指定范围内的均匀随机数,还能避免溢出问题。咱们写个小函数封装一下:
struct ExerciseInWorkout { let name: String let reps: Int } // 生成min到max之间的随机次数(包含两端) func randomReps(min: Int = 8, max: Int = 15) -> Int { guard max >= min else { return min } // 防止传入的范围不合理 let rangeSize = max - min + 1 return min + Int(arc4random_uniform(UInt32(rangeSize))) } // 现在动作库的每个动作都能拿到均匀分布的随机次数啦 let exerciseBankArray = [ ExerciseInWorkout(name: "Squat", reps: randomReps()), ExerciseInWorkout(name: "Push-Up", reps: randomReps(min: 10, max: 20)), ExerciseInWorkout(name: "Pull-Up", reps: randomReps(min: 5, max: 12)), // 继续加你的其他动作... ]
顺便优化下训练计划生成函数
如果你想生成3-6个不重复的动作,这个函数可以参考下,比单纯随机选更合理:
func generateRandomWorkout(from exerciseBank: [ExerciseInWorkout]) -> [ExerciseInWorkout]? { // 先确保动作库有足够多的动作可选 guard exerciseBank.count >= 3 else { return nil } // 随机选3-6个动作:arc4random_uniform(4)生成0-3,加3就是3-6 let exerciseCount = Int(arc4random_uniform(4)) + 3 // 打乱数组后取前N个,避免重复选同一个动作 let shuffledExercises = exerciseBank.shuffled() return Array(shuffledExercises.prefix(exerciseCount)) } // 调用示例 if let todayWorkout = generateRandomWorkout(from: exerciseBankArray) { print("今日训练计划:") for exercise in todayWorkout { print("- \(exercise.name): \(exercise.reps)次") } }
为啥之前的代码会抽风?
再给你解释下背后的原因:arc4random()返回的是0到UInt32.max(也就是42亿多)的随机数,直接转成Int在32位系统里会有一半概率变成负数,取模后结果就会集中在0、1、2这类小数值;如果是错误设置了范围(比如%3),那结果自然就是1、2居多,偶尔的14大概率是数值溢出导致的异常值。
用arc4random_uniform(_:)就没这些问题,它生成的是0到指定上限-1的均匀非负随机数,转成Int后完全符合预期。
内容的提问来源于stack exchange,提问作者nc14
相关产品推荐
相关产品推荐

