我正在try 生成一个完全随机的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()!

推荐答案

这是当前实现的浮点值随机数生成的限制-如果您查看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"
)

如果边界无效,代码会try 防止生成随机数,但不能充分处理溢出.有GitHub issue tracking this bug,但它似乎已经存在了一段时间-尽管有 comments 称这个问题将在SWIFT 5中得到修复,但这个修复还没有推出.

也许有必要对这个问题发表 comments ,或者在Swift forums上提出这个问题,在那里可以解决这个问题的工程师可以看到这一点.


同时,您提出的解决方案应该会让您足够接近,因为"足够接近"的定义是:您将获得一个在您想要的范围内的随机数字,尽管浮点精度的限制可能会影响您得到的数字的准确分布.根据您的用例,这可能并不重要,但在不了解更多信息的情况下,在引入完整的修复之前,这可能对您起作用,也可能不起作用.

您还可以try 在比[-1, 1]大得多的范围内生成一个随机数,并按较小的值对其进行zoom ,这可能会得到更准确的值分布.

Swift相关问答推荐

对多个项目的数组进行排序

如何设置两个不同的视图模型以在我的SwiftUI应用程序中使用相同的数据源?

如何在每天午夜重置布尔值

如何在SWIFT任务中判断当前任务是否已取消(异步/等待)

VisionOS TabBar预览中是否存在漏洞?

在SwiftUI中如何预览嵌套的ScrollView,以避免触发可刷新修饰符

使用View()和List()无法显示影子

如何使用 Swift 在非本地函数中切换()一个 Bool?

NavigationStack 和 TabView - 工具栏和标题不显示

如何在 SceneKit 上制作毛玻璃效果

使用 WrappingHStack 文本溢出到新行

当使用 CGFloat 而不是数字文字时,为什么 node 的位置会发生变化?

EXC_BREAKPOINT 崩溃的原因范围

Swift 协议只能设置?

快速在 LLDB 中使用 po

如何在 GCD 中停止 DispatchWorkItem?

如何快速识别字符串中的大写和小写字符?

在 Swiftui 中是否有一种简单的方法可以通过捏合来放大图像?

使用相机进行人脸检测

类型myViewController不符合 Swift 中的协议 UIPIckerDataSource