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(即全部)之间的随机数,然后将剩下的放入第五个桶中。
我不知道这是否是您想要的那种分布。它看起来应该给出合理的分布。
好吧,所以我想随机分配一个数字而不是均匀... 所以假设我们有 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(即全部)之间的随机数,然后将剩下的放入第五个桶中。
我不知道这是否是您想要的那种分布。它看起来应该给出合理的分布。