You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何无需循环从Sobol序列IEnumerable中逐个取值并封装为调用类

Sobol序列单次调用实现方案(VB.NET)

Sobol序列是取值范围为[0,1]的低差异随机数序列,原实现生成时首先需要初始化方向数向量:

Dim V(31) As ULong
For i = 1 To 31
  V(i-1) = 2 ^ (32 - i)
Next

原实现的遍历调用方式如下:

For Each lnumber As ULong In Sobol(V)
   MessageBox.Show(lnumber / 2 ^ 32)
Next

只要生成的数值数量少于2^32(线性同余生成器的典型周期),该方法即可正常运行。


需求说明

需要实现无需循环遍历,单次调用即可抽取一个Sobol数值的能力,预期使用方式如下:

  1. 任意位置实例化公共类:
Dim ran As New SobolNumber()
  1. 调用属性/方法获取下一个序列值:
Dim x as Double
x = ran.NextSobolNumber

原依赖的Sobol()及Ruler()函数代码如下:

Public Iterator Function Sobol(ByVal v() As ULong) As IEnumerable(Of ULong)
    Dim s As ULong = 0
    For Each r In Ruler()
        Yield s = s Xor v(r)
    Next r
End Function

Public Iterator Function Ruler() As IEnumerable(Of Integer)
    Yield 0
    For Each r In Ruler()
        Yield r + 1
        Yield 0
    Next r
End Function

最终实现代码

核心思路是将序列枚举器的状态封装到自定义类中,每次调用时移动枚举器返回对应值,完全兼容需求的调用规范:

Public Class SobolNumber
    ' 私有成员存储方向数向量和序列枚举器,保存迭代状态
    Private ReadOnly _directionVectors As ULong()
    Private ReadOnly _sobolEnumerator As IEnumerator(Of ULong)
    
    ' 构造函数:初始化方向数、绑定枚举器
    Public Sub New()
        ReDim _directionVectors(31)
        For i = 1 To 31
            _directionVectors(i - 1) = 2 ^ (32 - i)
        Next
        _sobolEnumerator = Sobol(_directionVectors).GetEnumerator()
    End Sub
    
    ' 对外暴露的取值属性
    Public ReadOnly Property NextSobolNumber As Double
        Get
            If _sobolEnumerator.MoveNext() Then
                Return _sobolEnumerator.Current / 2 ^ 32
            End If
            ' 超出2^32周期时抛出异常,可根据业务需求调整为返回默认值
            Throw New InvalidOperationException("Sobol序列已超出最大生成数量限制(2^32)")
        End Get
    End Property

    ' 封装依赖方法,无需外部调用
    Private Iterator Function Sobol(ByVal v() As ULong) As IEnumerable(Of ULong)
        Dim s As ULong = 0
        For Each r In Ruler()
            Yield s = s Xor v(r)
        Next r
    End Function

    Private Iterator Function Ruler() As IEnumerable(Of Integer)
        Yield 0
        For Each r In Ruler()
            Yield r + 1
            Yield 0
        Next r
    End Function
End Class

使用示例

完全符合预期调用逻辑:

' 全局或局部实例化均可
Dim ran As New SobolNumber()
' 任意位置逐次取值
Dim x As Double = ran.NextSobolNumber
Dim y As Double = ran.NextSobolNumber
Dim z As Double = ran.NextSobolNumber

内容的提问来源于stack exchange,提问作者user16594857

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.09.23 22:36:04