如何确保我的 RNG 号码是唯一的?
How can I make sure my RNG numbers are unique?
我正在尝试使用 RNG class 从列表中 select 2 个随机项目。问题是偶尔我会得到相同的 2 个数字,我希望它们是唯一的。我尝试使用 while 循环来获取另一个数字,如果它与上一个相同,但即使添加一个简单的 while 循环也会导致“超出预付 gas”错误。我有什么不明白的?
//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)
for(let i = 0; i < numItemsWanted; i++) {
var r = rng.next()
while (r == rng.last()) {
r = rng.next()
}
newList.push(oldList[r])
}
工作:
//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)
let r = rng.next()
let last = r + 1
for(let i = 0; i < numItemsWanted; i++) {
newList.push(oldList[r])
last = r
r = rng.next()
while (r == last) {
r = rng.next()
}
}
如果您从 oldList
中删除了一次选择的项目,将无法再次选择它。
另一种方法是洗牌 oldList
,然后选择前两项。
这是关于near-sdk-as
,NEAR平台上的AssemblyScript智能合约开发包
你可以在这个例子中看到RNG是如何使用的
https://github.com/Learn-NEAR/NCD.L1.sample--lottery/blob/ff6cddaa8cac4d8fe29dd1a19b38a6e3c7045363/src/lottery/assembly/lottery.ts#L12-L13
class Lottery {
private chance: f64 = 0.20
play(): bool {
const rng = new RNG<u32>(1, u32.MAX_VALUE);
const roll = rng.next();
logging.log("roll: " + roll.toString());
return roll <= <u32>(<f64>u32.MAX_VALUE * this.chance);
}
}
以及这里的构造函数是如何实现的:
https://github.com/near/near-sdk-as/blob/f3707a1672d6da6f6d6a75cd645f8cbdacdaf495/sdk-core/assembly/math.ts#L152
第一个参数是缓冲区的长度,其中包含从种子生成的随机数。您可以使用 next()
方法在每次调用时从此缓冲区中获取更多数字
export class RNG<T> {
constructor(len: u32, public max: u32 = 10_000) {
let real_len = len * sizeof<T>();
this.buffer = math.randomBuffer(real_len);
this._last = this.get(0);
}
next(): T {}
}
我正在尝试使用 RNG class 从列表中 select 2 个随机项目。问题是偶尔我会得到相同的 2 个数字,我希望它们是唯一的。我尝试使用 while 循环来获取另一个数字,如果它与上一个相同,但即使添加一个简单的 while 循环也会导致“超出预付 gas”错误。我有什么不明白的?
//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)
for(let i = 0; i < numItemsWanted; i++) {
var r = rng.next()
while (r == rng.last()) {
r = rng.next()
}
newList.push(oldList[r])
}
工作:
//simplified for posting question
var lengthOfList = 10
var numItemsWanted = 2
//Get more rng numbers than I need incase of duplicates
const rng = new RNG<u32>(lenghtOfList, lengthOfList)
let r = rng.next()
let last = r + 1
for(let i = 0; i < numItemsWanted; i++) {
newList.push(oldList[r])
last = r
r = rng.next()
while (r == last) {
r = rng.next()
}
}
如果您从 oldList
中删除了一次选择的项目,将无法再次选择它。
另一种方法是洗牌 oldList
,然后选择前两项。
这是关于near-sdk-as
,NEAR平台上的AssemblyScript智能合约开发包
你可以在这个例子中看到RNG是如何使用的 https://github.com/Learn-NEAR/NCD.L1.sample--lottery/blob/ff6cddaa8cac4d8fe29dd1a19b38a6e3c7045363/src/lottery/assembly/lottery.ts#L12-L13
class Lottery {
private chance: f64 = 0.20
play(): bool {
const rng = new RNG<u32>(1, u32.MAX_VALUE);
const roll = rng.next();
logging.log("roll: " + roll.toString());
return roll <= <u32>(<f64>u32.MAX_VALUE * this.chance);
}
}
以及这里的构造函数是如何实现的: https://github.com/near/near-sdk-as/blob/f3707a1672d6da6f6d6a75cd645f8cbdacdaf495/sdk-core/assembly/math.ts#L152
第一个参数是缓冲区的长度,其中包含从种子生成的随机数。您可以使用 next()
方法在每次调用时从此缓冲区中获取更多数字
export class RNG<T> {
constructor(len: u32, public max: u32 = 10_000) {
let real_len = len * sizeof<T>();
this.buffer = math.randomBuffer(real_len);
this._last = this.get(0);
}
next(): T {}
}