当前位置: 首页 > 面试题库 >

随机百分比分支的编码模式?

养枫涟
2023-03-14
问题内容

假设我们有一个代码块,我们要执行70%的时间,又要执行30%的时间。

if(Math.random() < 0.7)
    70percentmethod();
else
    30percentmethod();

很简单。但是,如果我们希望它可以轻松扩展为30%/ 60%/
10%等呢?在这里,这将需要添加和更改所有if语句,这些if语句使用起来并不十分好,而且很慢并且容易引发错误。

到目前为止,我发现大型开关对于此用例非常有用,例如:

switch(rand(0, 10)){
    case 0:
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:70percentmethod();break;
    case 8:
    case 9:
    case 10:30percentmethod();break;
}

可以很容易地将其更改为:

switch(rand(0, 10)){
    case 0:10percentmethod();break;
    case 1:
    case 2:
    case 3:
    case 4:
    case 5:
    case 6:
    case 7:60percentmethod();break;
    case 8:
    case 9:
    case 10:30percentmethod();break;
}

但是这些也有它们的缺点,它们麻烦并且被划分为预定数量的划分。

我认为某种理想的方法是基于“频率数”系统,例如:

(1,a),(1,b),(2,c) -> 25% a, 25% b, 50% c

然后,如果您添加了另一个:

(1,a),(1,b),(2,c),(6,d) -> 10% a, 10% b, 20% c, 60% d

因此,简单地将数字相加,使总和等于100%,然后将其分割即可。

我想用自定义的哈希图或类似的东西为其创建处理程序不会有太大的麻烦,但是我想知道在我将所有意大利面条用于此之前是否有某种确定的方式/模式或lambda。


问题答案:

编辑: 请参阅最后的编辑,以获取更优雅的解决方案。我会留在这。

您可以使用NavigableMap存储映射到其百分比的这些方法。

NavigableMap<Double, Runnable> runnables = new TreeMap<>();

runnables.put(0.3, this::30PercentMethod);
runnables.put(1.0, this::70PercentMethod);

public static void runRandomly(Map<Double, Runnable> runnables) {
    double percentage = Math.random();
    for (Map.Entry<Double, Runnable> entry : runnables){
        if (entry.getKey() < percentage) {
            entry.getValue().run();
            return; // make sure you only call one method
        }
    }
    throw new RuntimeException("map not filled properly for " + percentage);
}

// or, because I'm still practicing streams by using them for everything
public static void runRandomly(Map<Double, Runnable> runnables) {
    double percentage = Math.random();
    runnables.entrySet().stream()
        .filter(e -> e.getKey() < percentage)
        .findFirst().orElseThrow(() -> 
                new RuntimeException("map not filled properly for " + percentage))
        .run();
}

NavigableMap分类
(例如HashMap没有给出该项目的担保)的按键,让您获得通过他们的百分比排序的条目。这是相关的,因为如果您有两项 (3,r1)
(7,r2) ,它们将产生以下条目:r1 = 0.3并且r2 = 1.0需要按此顺序进行评估(例如,如果按相反的顺序进行评估,则结果将 永远
r2)。

至于拆分,它应该是这样的:使用类似Tuple的类

static class Pair<X, Y>
{
    public Pair(X f, Y s)
    {
        first = f;
        second = s;
    }

    public final X first;
    public final Y second;
}

您可以像这样创建地图

// the parameter contains the (1,m1), (1,m2), (3,m3) pairs
private static Map<Double,Runnable> splitToPercentageMap(Collection<Pair<Integer,Runnable>> runnables)
{

    // this adds all Runnables to lists of same int value,
    // overall those lists are sorted by that int (so least probable first)
    double total = 0;
    Map<Integer,List<Runnable>> byNumber = new TreeMap<>();
    for (Pair<Integer,Runnable> e : runnables)
    {
        total += e.first;
        List<Runnable> list = byNumber.getOrDefault(e.first, new ArrayList<>());
        list.add(e.second);
        byNumber.put(e.first, list);
    }

    Map<Double,Runnable> targetList = new TreeMap<>();
    double current = 0;
    for (Map.Entry<Integer,List<Runnable>> e : byNumber.entrySet())
    {
        for (Runnable r : e.getValue())
        {
            double percentage = (double) e.getKey() / total;
            current += percentage;
            targetList.put(current, r);
        }
    }

    return targetList;
}

所有这些都添加到一个类中

class RandomRunner {
    private List<Integer, Runnable> runnables = new ArrayList<>();
    public void add(int value, Runnable toRun) {
        runnables.add(new Pair<>(value, toRun));
    }
    public void remove(Runnable toRemove) {
        for (Iterator<Pair<Integer, Runnable>> r = runnables.iterator();
            r.hasNext(); ) {
            if (toRemove == r.next().second) {
               r.remove();
               break;
            }
        }
    }
    public void runRandomly() {
        // split list, use code from above
    }
}

编辑:
实际上,以上就是如果您有一个想法陷在头脑中,并且没有正确地质疑它,您会得到什么。保留RandomRunner类接口,这要容易得多:

class RandomRunner {
    List<Runnable> runnables = new ArrayList<>();
    public void add(int value, Runnable toRun) {
        // add the methods as often as their weight indicates.
        // this should be fine for smaller numbers;
        // if you get lists with millions of entries, optimize
        for (int i = 0; i < value; i++) {
            runnables.add(toRun);
        }
    }
    public void remove(Runnable r) {
        Iterator<Runnable> myRunnables = runnables.iterator();
        while (myRunnables.hasNext()) {
            if (myRunnables.next() == r) {
                myRunnables.remove();
            }
    }
    public void runRandomly() {
        if (runnables.isEmpty()) return;
        // roll n-sided die
        int runIndex = ThreadLocalRandom.current().nextInt(0, runnables.size());
        runnables.get(runIndex).run();
    }
}


 类似资料:
  • 问题内容: 我已经在服务器上用PHP和bash编写了一个完整的系统,以便在VPS上转换和流式传输HTML5中的视频。转换由ffmpeg在后台完成,其内容输出到 block.txt 。 除其他外,我找不到有效的例子。 我需要获取当前编码进度的百分比。 我上面链接的第一篇文章给出了: $ percent_extracted变量回显零,由于数学不是我的强项,所以我真的不知道如何在这里继续。 这是来自bl

  • Azure正在返回404指定的blob不存在。当它存在时,我可以毫无问题地浏览到相关文件。实际上,文件路径是由我的脚本从之前对https://${vault}的调用生成的。水滴。果心窗户。net/${container}?重新类型=容器 但是,DELETE调用返回404(您可以在下面看到我的标头结构以及Azure响应): 我使用的是一个Perl脚本(该脚本从容器/列表API中通过XML并删除早于X

  • 如何对字符串进行百分比编码,如RFC 3986中所述?也就是说,我不想(依我看,很奇怪)对www url表单进行编码,因为这是不同的。 如果重要的话,我正在编码的数据不一定是一个完整的URL。

  • 问题内容: 我正在使用Elasticsearch 1.7.3累积用于分析报告的数据。 我有一个包含文档的索引,其中每个文档都有一个名为“ duration”的数字字段(请求花费了几毫秒)和一个名为“ component”的字符串字段。可能有许多具有相同组件名称的文档。 例如。 我想生成一份报告,说明每个组件: 此组件的所有“持续时间”字段的总和。 此总和在 所有 文档的总期限中所占的百分比。在我的

  • 使用。getDownloadUrl()可以给出来自Firebase存储的编码URL的百分比。在本例中,我想上传一个文件到子文件夹“Images”。这是上传代码。 是否有一些元数据我应该传递上传,以停止百分比编码发生?

  • 我看到了这张非常漂亮的信息图,它大致估计了用于某些操作的CPU周期。在学习的时候,我注意到了一个条目“如果的右分支”,我假设如果满足条件,“如果”将要分支(编辑:正如评论中指出的,“右”实际上意味着“正确预测的分支”)。这让我怀疑if分支与else分支相比是否存在任何(甚至如此微小)速度差异。 例如,比较以下非常简洁的代码: 演示 它在x86 64bit中生成此程序集: 如您所见,右边的分支为“a