C#学习教程:生成一个具有一定最大值的均匀随机整数我已经有了一个生成器,它可以在整个内置无符号整数类型范围内返回统一的值。让我们调用byteByte()方法byteByte()、ushortUInt16()、uintUInt32()和ulongUInt64()。假设这些方法的结果是完全一致的。我想要的方法的签名是uintUniformUInt(uintmaxValue)和ulongUniformUInt(ulongmaxValue)。我在寻找什么:正确性我更喜欢在给定的时间间隔内分配返回值。但是,如果性能得到显着改善,非常小的偏差是可以接受的。我的意思是一个阶的偏差,允许鉴别器在给定2^64个值的情况下有2/3的概率。它必须适用于任何最大值。性能这种方法应该很快。效率该方法确实消耗了很少的原始随机性,因为根据底层生成器的不同,生成原始字节的成本可能很高。浪费几位很好,但消耗128位来生成一个数字可能有点矫枉过正。在某些成员变量中,还可以缓存来自先前调用的一些遗留随机性。小心int溢出和环绕行为。我已经有了一个解决方案(我会把它作为答案发布),但它对我来说有点难看。所以我想获得更好的解决方案的想法。关于如何使用较大的maxValue进行单元测试的建议也很好,因为我无法生成具有2^64个桶和2^74个随机值的直方图。另一个复杂的因素是只有一些最大值分布对某些错误有很大的偏差,而其他的只有很小的偏差。这样的通用解决方案怎么样?该算法基于Java的nextInt方法使用的算法,拒绝任何会导致非均匀分布的值。只要您的UInt32方法的输出完全相同,那么这也应该如此。uintUniformUInt(uintinclusiveMaxValue){未选中{uintexclusiveMaxValue=inclusiveMaxValue+1;//如果exclusiveMaxValue是2的幂,那么我们可以只使用掩码//也处理inclusiveMaxValue为uint.MaxValue的边缘情况if((exclusiveMaxValue&(~exclusiveMaxValue+1))==exclusiveMaxValue)returnUInt32()&inclusiveMaxValue;单位位,val;做{位=UInt32();val=bits%exclusiveMaxValue;//如果(bits-val+inclusiveMaxValue)溢出,则val已从位范围末尾的不完整块中获取//在这种情况下,我们拒绝它并再次循环}while(bits-val+inclusiveMaxValueIn理论上,拒绝过程可以永远循环;在实践中,性能应该相当好。在不了解(a)预期使用模式和(b)底层RNG的性能特征的情况下,很难提出任何普遍适用的优化建议。对于例如,如果大多数调用者将指定最大熵位非常昂贵,其他一切都应该被认为是昂贵的,但不如熵。我的想法是使用二进制数到一半,四分之一...maxValue空间,直到它减少到一个数字。有点像我使用maxValue=333(十进制)作为示例并假设函数getBit()随机返回0或1offset:=0space:=maxValuewhile(space>0)//Right-shiftthevalue,保持最右边的位这应该是//在x86和x64上有效,如果用真实代码编码,则伪代码保持不变:=space&1part:=floor(space/2)space:=part//在333示例中,部分现在是166,但是2*166=332如果我们简单地选择一个//一半的空间,我们会严重偏向上半部分,所以如果//我们有剩余部分,我们会消耗一点熵决定哪一半更大if(remains)if(getBit())part++;//现在我们决定选择哪一半,消耗一点熵if(getBit())offset+=part;//退出条件:保证满足remeindnumberspace=0//在333示例中,offset将为0、166或167,剩余空间将为166}randomResult:=offsetgetBit()可以来自你的熵源,如果它是基于位的,或者在第一次调用时一次消耗n位熵(显然n是您的熵源的最佳值),并将其转换为无。我目前的解决方案对我来说有点难看。每个生成的数字也有两个分区,这可能会对性能产生负面影响(我还没有分析这部分)。以上就是《C#学习教程:生成具有一定最大值的均匀随机整数》全部内容分享。如果对大家有用,需要详细了解C#学习教程,希望大家多多关注---uintUniformUInt(uintmaxResult){uintrand;uint计数=maxResult+1;如果(最大结果=有用计数);返回兰特%计数;}elseif(maxResult=usefulCount);返回兰特%计数;}elseif(maxResult!=uint.MaxValue){uintusefulCount=(uint.MaxValue/count)*count;//将上限减1,以避免长除法do{rand=UInt32();}while(rand>=usefulCount);返回兰特%计数;}else{返回UInt32();}}ulongUniformUInt(ulongmaxResult){if(maxResult=usefulCount);返回兰特%计数;}否则返回UInt64();删除。如需转载请注明出处:
