Visual Basic 根据除数随机除以双精度

Visual Basic Divide Double Randomly based on Divisor

好吧,所以我想随机分配一个数字而不是均匀... 所以假设我们有 20 个我需要 5 个(除数)随机块 20.

4 4 4 4 4

相反,我想要

6 2 4 3 5

不能超过起始数

如何在 vb 中完成?

请帮忙,被困了几个小时。

Public Iterator Function DivideUp(ByVal Number As Integer, ByVal Groups As Integer, Optional ByVal Variance As Integer = 5) As IEnumerable(Of Integer)
    Dim rnd As New Random()

    While Groups > 0 AndAlso Number > 0 
       If Groups = 1 Then
           Yield Number
           Exit Function
       End If
       If Variance > Number - Groups Then Variance = Number - Groups

       Dim temp As Integer = Number / Groups
       temp += rnd.Next(Variance * -1, Variance)

       Yield temp
       Number -= temp
       Groups -= 1
    End While
End Function

这样称呼它:

For Each num As Integer In DivideUp(20, 5)
    Console.WriteLine(num)
Next

更常规的东西:

Public Function DivideUp(ByVal Number As Integer, ByVal Groups As Integer, Optional ByVal Variance As Integer = 5) As Integer()
    Static rnd As New Random()

    Dim result(Groups-1) As Integer
    For i As Integer = 0 To Groups - 1
       If Variance > Number - Groups Then Variance = Number - Groups
       If i = Groups - 1 Then
           result(i) = Number
       Else
           Dim temp As Integer = Number / Groups
           temp += rnd.Next(Variance * -1, Variance)
           result(i) = temp
           Number -= temp
       End If
    Next i
    Return result
End Function

如果你想得到真正的幻想,你可以使用随机方差的对数或自然对数来尝试让它更接近中位数,即:如果你的数字平均分为 4 组,你想让 2 比 3 少见,1 比 2 少见吗?

最后,一个测试工具:

Dim errorCount As Integer = 0
For i As Integer = 0 To 10000
    Dim items = DivideUp(100, 12)
    Dim sum As Integer = 0 
    For Each j As Integer In items
        Console.Write(j)
        Console.Write(" ")
        sum += j
    Next j   
    Console.WriteLine("Total: {0}", sum)
    If sum <> 100 Then
        errorCount += 1
        Dim tempColor = Console.ForegroundColor
        Console.ForegroundColor = ConsoleColor.Red
        Console.WriteLine("Error: incorrect total!")
        Console.ForegroundColor = tempColor
    End If     
Next i
If errorCount > 0 Then
    Dim tempColor = Console.ForegroundColor
    Console.ForegroundColor = ConsoleColor.Red
    Console.WriteLine("Error: incorrect total on {0} tries!")
    Console.ForegroundColor = tempColor
End If

如果你用的是真钱,你需要使用加密随机数生成器(简单的 Random 类型不会削减它)并且你想实际保存这些结果中的每一个(加上运行 它更像是几百万次,而不是仅仅 10,000 次)。然后,您将该数据提取到 R 之类的工具中并绘制分布图,以确保数据平坦(均匀分布),没有明显的偏差。您必须对许多不同的 Number/Group/Variance 组合执行此操作。未能严格验证清除任何偏差的随机性 导致有人玩弄您的系统以比他们应有的次数更频繁地获胜。

这取决于您希望值的分布是什么样子。有什么限制?比如,您是否希望它们都大致相等,比如每个大约占总数的 1/5,但有一些变化?或者是否可以接受 and/or 可取的,比如说,第一个桶有大约一半,第二个桶大约有一半,等等?任何桶都必须有 0 到 20 之间的任何数字吗?还是 0 是不可接受的值?等等

考虑到所有这些,我首先想到的解决方案是:

function deal(total as integer, bucket_count as integer) as buckets() as integer
  dim r as new random()
  dim buckets(bucket_count-1) as integer
  for bx=0 to bucket_count-2
    buckets(bx)=r.next(total*2/(bucket_count-bx))
    total-=buckets(bx)
  next
  buckets(bucket_count-1)=total
  return buckets
end function

我还没有测试过这段代码,所以如果有错误请见谅,但基本思路是:

我们希望每个桶获得总量的大约 1/5。所以我为第一个桶分配了一个介于 0 和 2/5 之间的随机数。然后我从 运行 总数中减去这个数字,然后我为第二个桶分配一个介于 0 到 2/4 之间的随机数,然后第三个桶分配一个介于 0 到 2/3 之间的随机数。也就是说,第四个桶是一个介于 0 和 2/2(即全部)之间的随机数,然后将剩下的放入第五个桶中。

我不知道这是否是您想要的那种分布。它看起来应该给出合理的分布。