我正在尝试生成一个完全随机的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 nouniform distribution on anInfinite range
但是,范围不应该是无限的。检查 Playground 中的最小值和最大值或范围本身表明,边界是 -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()!
最佳答案
这是当前浮点值随机数生成实现的限制 - 如果您查看 stdlib/public/core/FloatingPointRandom.swift:156
(就在错误消息指向的地方),您可以看到此限制来自何处:
let delta = range.upperBound - range.lowerBound
// TODO: this still isn't quite right, because the computation of delta
// can overflow (e.g. if .upperBound = .maximumFiniteMagnitude and
// .lowerBound = -.upperBound); this should be re-written with an
// algorithm that handles that case correctly, but this precondition
// is an acceptable short-term fix.
_precondition(
delta.isFinite,
"There is no uniform distribution on an infinite range"
)
如果边界无效,代码会尝试阻止生成随机数,但不能充分处理溢出。有一个GitHub issue tracking this bug ,但它似乎已经存在了一段时间 - 尽管有评论指出这将在 Swift 5 中修复,但该修复尚未引入。
可能值得对这个问题发表评论,或者在 Swift forums 上提出这个问题。 ,可以解决该问题的工程师可以在其中看到这一点。
与此同时,您提出的解决方案应该让您足够接近,对于“足够接近”的某些定义:您将获得所需范围内的随机数,尽管浮点精度的限制可能会影响你得到的数字的精确分布。根据您的用例,这可能并不重要,但在不了解更多信息的情况下,在引入完整修复之前,这可能对您有用,也可能不起作用。
您还可以尝试生成一个比 [-1, 1]
范围大得多的随机数,并按较小的比例对其进行缩放,这可能会让您获得更准确的值分布.
关于Swift随机浮点 fatal error : no uniform distribution on an infinite range,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/75467199/