Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/javascript/403.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Javascript按随机百分比执行函数_Javascript_Random - Fatal编程技术网

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}`);
}