我试图生成一个完全随机的float
值,这应该很容易。然而,它不起作用,而且从它的外观来看,也许我是第一个遇到这个错误的人?我当然似乎找不到任何以前的帖子。
此代码:
let min = -Float.greatestFiniteMagnitude
let max = +Float.greatestFiniteMagnitude
let range = min...max
let random = Float.random(in: range)
一直工作到最后一行,该行失败,生成Swift/FloatingPointRandom.swift:162: Fatal error: There is no uniform distribution on an infinite range
然而,范围不应该是无限的,检查最小值和最大值或者操场上的范围本身,就会发现范围是-3.402823e+38
到3.402823e+38
,两者都不是无限的。
这是怎么回事?有没有一个我错过的正确的方法来做这件事?除了以下几点,对于这样一个简单的任务来说,这似乎非常复杂:
let min = Float(0)
let max = Float.greatestFiniteMagnitude
let range = min...max
let signs : [Float] = [-1, 1]
let random = Float.random(in: range) * signs.randomElement()!
1条答案
按热度按时间hzbexzde1#
这是当前实现浮点值随机数生成的一个局限性-如果您检查
stdlib/public/core/FloatingPointRandom.swift:156
(就在错误消息所指向的位置附近),您可以看到这个局限性来自哪里:如果边界无效,代码会尝试阻止生成随机数,但无法充分处理溢出。有一个GitHub issue tracking this bug,但似乎已经存在一段时间了-虽然有一个评论说这将在Swift 5中得到修复,但该修复尚未引入。
这个问题可能值得评论,或者在Swift forums上提出这个问题,可以解决这个问题的工程师可以看到这个问题。
与此同时,您建议的解决方案应该让您足够接近,对于“足够接近”的某些定义来说:你会得到一个你想要的范围内的随机数,尽管浮点精度的限制可能会影响你得到的数字的确切分布。根据你的使用情况,这可能并不重要,但如果不知道更多,这可能会或可能不会为你工作,直到一个完整的修复被引入。
您还可以尝试在比
[-1, 1]
大得多的范围内生成随机数,并将其缩放较小的量,这样可以获得更准确的值分布。