Swift随机浮点致命错误:在无限范围内非均匀分布

k4ymrczo  于 2023-02-18  发布在  Swift
关注(0)|答案(1)|浏览(114)

我试图生成一个完全随机的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+383.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()!
hzbexzde

hzbexzde1#

这是当前实现浮点值随机数生成的一个局限性-如果您检查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]大得多的范围内生成随机数,并将其缩放较小的量,这样可以获得更准确的值分布。

相关问题