Javascript按随机百分比执行函数
比方说,我想通过百分比概率触发一个函数Javascript按随机百分比执行函数,javascript,random,Javascript,Random,比方说,我想通过百分比概率触发一个函数 function A () { console.log('A triggered'); } //50% chance to trigger if (Math.random() >= 0.5) A(); 现在,我想添加更多的函数,以便偶然触发,我所做的是 //method 1 function B () { console.log('B triggered'); } //10% chance to trigger function C () { c
function A () { console.log('A triggered'); } //50% chance to trigger
if (Math.random() >= 0.5) A();
现在,我想添加更多的函数,以便偶然触发,我所做的是
//method 1
function B () { console.log('B triggered'); } //10% chance to trigger
function C () { console.log('C triggered'); } //10% chance to trigger
if (Math.random() >= 0.5) {
A();
} else if (Math.random() > (0.5 + 0.1)) {
B();
} else if (Math.random() > (0.5 + 0.1 + 0.1)) {
C();
}
但是这使得A()
在B()和C()之前获得优先级。因此,我将代码更改为
//method 2
var randNumber = Math.random();
if (randNumber <= 0.5) { A(); }
else if (randNumber > 0.5 && randNumber <= (0.5 + 0.1)) { B(); }
else if (randNumber > (0.5 + 0.1) && randNumber <= (0.5 + 0.1 + 0.1)) { C(); }
//方法2
var randNumber=Math.random();
if(随机数0.5&&randNumber(0.5+0.1)&&randNumber
这种方法看起来很公平,但效率很低,因为它需要在每一个if-else
没错,虽然下限是不必要的,因为您使用的是else
。此外,使用数学使其看起来比实际情况更复杂:
var randNumber = Math.random();
if (randNumber <= 0.5) { A(); }
else if (randNumber <= 0.6) { B(); }
else if (randNumber <= 0.7) { C(); }
请注意,尽管上面是用数字文字编写的,分派
对象的属性名称实际上是字符串(“0”
,“1”
,等等)
不过,使用列表比使用此分派对象要好
基本上,这意味着避免(某些)分数值并保持在合理的数值范围内。例如,如果您的计算结果类似于0.009/3
,并且您(合理地)希望能够使用“0.003”
作为键,那么它将不起作用,因为字符串(0.009/3)
是“0.002999999999996”
,而不是“0.003”
,这要归功于IEEE-754双精度二进制浮点不精确。(而0.09/3
很好,给我们“0.03”
).您可以创建一个要调用的函数及其被调用机会的列表。然后使用这些机会将随机数的范围划分为块。在本例中,它是:
0.0 0.5 0.6 0.7
0.5/A 0.1/B 0.1/C
不需要根据几率对条目进行排序。如果几率之和大于1.0,则不会调用数组的最后一个元素。这是使用这种方法需要确保的
代码可能如下所示:
函数A(){
console.log('A被调用')
}
函数B(){
console.log('B被调用')
}
函数C(){
log('C被调用')
}
变量列表=[
{chance:0.5,func:A},
{chance:0.1,func:B},
{chance:0.1,func:C}
];
函数调用随机函数(列表){
var rand=Math.random()//获取一个介于0和1之间的随机数
var AccumagedChance=0//用于计算当前
var found=list.find(函数(元素){//遍历所有元素
累计机会+=元素。机会//累计机会
return accumulatedChance>=rand//测试元素是否在范围内,如果是,则此项存储在“found”中
})
如果(找到){
console.log('找到的匹配项为:'+rand)
found.func()
}否则{
console.log('找不到与:'+rand的匹配项)
}
}
callRandomFunction(list)
这是我将如何进行布局的
let outcomes = [
{ chance: 50, action:() => { console.log('A'); } },
{ chance: 10, action:() => { console.log('B'); } },
{ chance: 10, action:() => { console.log('C'); } }
]
function PerformAction(actions){
let totalChance = actions.reduce((accum, current)=>{
return accum + current.chance;
}, 0);
if(totalChance > 100){
throw Error('Total chance cannnot exceed 100%');
}
if(totalChance < 100) {
actions.push({
chance: 100 - totalChance,
action: function(){
console.log('No action taken');
}
})
}
let outcome = Math.random() * 100;
actions.find((current)=>{
outcome = outcome - current.chance;
return outcome <= 0;
}).action();
}
PerformAction(outcomes);
让结果=[
{chance:50,action:()=>{console.log('A');},
{chance:10,action:()=>{console.log('B');},
{chance:10,action:()=>{console.log('C');}
]
功能执行(动作){
让totalChance=动作。减少((累计,当前)=>{
返回累计+当前机会;
}, 0);
如果(totalChance>100){
投掷错误('总概率不能超过100%');
}
如果(总概率<100){
动作。推({
机会:100-总机会,
行动:功能(){
console.log(“未采取任何操作”);
}
})
}
让结果=Math.random()*100;
actions.find((当前)=>{
结果=结果-当前机会;
返回结果让我们把它分成几个部分:
1) 范围
创建一个具有所有范围上限的数组,例如,假设您想要以下范围0-10、11-20和21-100,那么该数组将为:
const arr = [10, 20, 100]
为了找到正确的范围:
let randNumber = Math.random() * 100;
let rangeFound = false;
for (i = 0; i < arr.length && !rangeFound; i++) {
let lowerBound = i>0?arr[i-1]:-1,
upperBound = arr[i];
if(randNumber > lowerBound && randNumber <= upperBound){
//save a reference to the current range (index?)
rangeFound = true;
}
}
Ir为了保存“范围索引”并知道应该触发哪个函数,我将在下面的代码中使用变量rangeIndex
function A() { /*do something A*/}
function B() { /*do something B*/}
function C() { /*do something C*/}
const arr = [10, 20, 100];
const func = [A, B, C];
let randNumber = Math.random() * 100;
let rangeFound = false;
let rangeIndex = -1;
for (i = 0; i < arr.length && !rangeFound; i++) {
let lowerBound = i>0?arr[i-1]:-1,
upperBound = arr[i];
if(randNumber > lowerBound && randNumber <= upperBound){
rangeIndex = i;
rangeFound = true;
}
}
if(rangeFound){
let f = func[rangeIndex];
f();
} else {
console.warn(`There is no suitable range for ${randNumber}`);
}
函数A(){/*做点什么A*/}
函数B(){/*执行某些操作B*/}
函数C(){/*执行某些操作C*/}
常数arr=[10,20,100];
常量func=[A,B,C];
设randNumber=Math.random()*100;
让rangeFound=false;
设rangeIndex=-1;
对于(i=0;i0?arr[i-1]:-1,
上限=arr[i];
如果(randNumber>lowerBound&&randNumber您可以省略&&
之前的条件,因为它们总是true@RyanSearle很好的一点,thx指出如果你有太多的函数,它们的概率加起来超过1.0?那么它应该如何运行?@SergioTulentsev很好。这将是我案例中的声明问题,仅此而已假设所有函数的总概率不会超过100%,我喜欢你对调度对象的处理方式。只是为了挑剔,如果概率百分比是一个整数
,那么如果概率百分比是0.2%
,那就需要在1-1000之间随机,我必须放置de>10%
函数值乘以100?它不应该是var f=dispatch[Math.floor(Math.random()*10)];?用括号代替parenthesis@duatis:谢谢,拼写错误已修复。:-)@Dean-我不完全确定我知道你的意思,但听起来你最终会得到一个包含1000个条目的分派
对象。这很好,尽管可能不太合适。你必须小心避免分数不精确的问题。你的例子很好,谢谢。但是几乎没有错误I
而不是rangeFound
,Math.random()*100
而不是Math.random
否则它只能得到第一个函数
const arr = [10, 20, 100]
let randNumber = Math.random() * 100;
let rangeFound = false;
for (i = 0; i < arr.length && !rangeFound; i++) {
let lowerBound = i>0?arr[i-1]:-1,
upperBound = arr[i];
if(randNumber > lowerBound && randNumber <= upperBound){
//save a reference to the current range (index?)
rangeFound = true;
}
}
const func = [A, B, C]
function A() { /*do something A*/}
function B() { /*do something B*/}
function C() { /*do something C*/}
const arr = [10, 20, 100];
const func = [A, B, C];
let randNumber = Math.random() * 100;
let rangeFound = false;
let rangeIndex = -1;
for (i = 0; i < arr.length && !rangeFound; i++) {
let lowerBound = i>0?arr[i-1]:-1,
upperBound = arr[i];
if(randNumber > lowerBound && randNumber <= upperBound){
rangeIndex = i;
rangeFound = true;
}
}
if(rangeFound){
let f = func[rangeIndex];
f();
} else {
console.warn(`There is no suitable range for ${randNumber}`);
}