2

問題文: パーセンテージを一致させて、さまざまなコマンドをランダムに実行します。CommandA を 50% の時間で実行し、commandB を 25% の時間で実行し、commandC を 15% の時間で実行するなど、合計パーセンテージは 100% にする必要があります。

私の質問は- CommandA A% の時間、CommandB B% の時間、CommandC C% の時間 ----- CommandZ Z% の時間を実行します。そして、合計パーセンテージは100%である必要があり、最後に、合計実行が完了した後、各コマンドが実行されている回数と各コマンドのパーセンテージ(パーセンテージで各コマンドが実行されている回数を意味します)を確認できます.

アイデア:- 1 から 100 までの乱数を生成し、パーセンテージのいずれかがカテゴリに該当するかどうかを確認します。

List<Double> comamndDistribution = new ArrayList<Double>();

    /* Commands to execute. Here I have Z command 
    *  and total percentage should be 100% (A+B+C+D+...+Z=100%)
    */
        comamndDistribution.add(A%); // command A
        comamndDistribution.add(B%); // command B
        comamndDistribution.add(C%); // command C
        comamndDistribution.add(D%); // command D
        comamndDistribution.add(E%); // command E
        -----------
        -----------
        comamndDistribution.add(Z%); // command Z

private Command getNextCommandToExecute() {

    for (int i=0; i < 10000; i++) {
       // generating a random number between 1 and 100
      int random = r.nextInt(100-1) + 1;

    /* My Question is- Execute CommandA A% of time, CommandB B% 
       of time, CommandC C% of time ----- Command Z Z% of time. 
       And total percentage should be 100% and at the end I can see
       how much times each command is being executed and what is 
       the percentage of each command(means how many times each command is 
       being executed in terms of percentage) after total execution is complete.
    */
        }
}

/* Get the next command to execute by maintaining the Percentage of 
    each command randomly*/
    Command nextCommand = getNextCommandToExecute();

もっと明確にしましょう- 私の質問は- CommandA A% の時間、CommandB B% の時間、CommandC C% の時間 ----- コマンド NN% の時間を乱数を使用して実行します。また、合計パーセンテージは 100% である必要があります。

PS: この質問は何度か聞かれたと思いますが、私が望んでいた方法ではありません。そこで、これまでのコードを投稿することで、もう一度質問として入れようと思いました。

更新:-人々がより理解できるように、別のロジックで書いた以前のコードを削除して質問を更新しました。

4

2 に答える 2

0

これはあなたが尋ねたものではありませんが、私はそれがあなたが意図したものだと思います。

class RandomCommands {
  // A Map that associates each command with a threshold from 0 - totalWeights.
  // The order of iteration is the same as the order of insertion.
  private Map<int, Command> commands = new LinkedHashMap<int, Command>>();

  // Running total of the weights of all of the commands.  The likelihood that
  // particular command will be executed is its weight / totalWeights.
  private int totalWeights = 0;

  // Adds a command with the specified weight, which can be any positive integer.
  public void addCommand(int weight, Command command) {
    commands.put(totalWeights, command);
    totalWeights += weight;
  }

  // Chooses a random command.
  public Command getRandomCommand() {
    // Choose a random number to select a command.
    int selector = Random.nextInt(totalWeights);

    // Find the corresponding command.
    for (Element<int, Command> command : commands) {
      if (command.key >= selector) {
        return command.value;
      }
      selector -= command.key;
    }
  }
}

例:

重みが20、20、40の3つのコマンドがあるとします。重みの合計は80なので、次のように計算できます。

  • 最初の2つのコマンドはそれぞれ、20/80 = 1/4 = 25%の確率で選択されます。
  • 3番目のコマンドは40/80=1/2 = 50%の確率で選択されます。

commandsマップには次のエントリが含まれます。

<0,  Command1>
<20, Command2>
<40, Command3>

が呼び出されるたびgetRandomCommand()に、0から79までの乱数が選択されます。次のようにコマンドの1つが返されます。

セレクタコマンドの実行頻度
———————— ——————— ———————————————————————————————————— ————
 0-19コマンド1(1 + 19-0)/ 80 = 20/80 = 1/4 = 25%
20-39コマンド2(1 + 39-20)/ 80 = 20/80 = 1/4 = 25%
40-79コマンド3(1 + 79-40)/ 80 = 40/80 = 1/2 = 50%
于 2012-05-19T04:49:11.603 に答える
0

Adam Liss と同様の方法で作成しましたが、より冗長であることがわかりました。

繰り返しになりますが、提供されたコマンドの合計が常に 100% になることに頼ることはできないと思ったので、それに対処しましたが、私の方法では、比率を再正規化するためにメソッド呼び出しが必要です (そのため、エラーが発生しやすくなります)。

import java.util.*;

/** 
  A basic 'Command' class for testing
*/
class Command {
  private String id;
  public Command (String pId) {
    this.id = pId;
  }
  public void execute () {
    System.out.println ("Command: "+id);
  }
}

/** The class that does the random selection bit of magic */
public class CommandDist {

  /** an internal helper class to manage proportions and the command */
  class Cmd {
    Command command;                 // the command that will get executed
    double assignedProportion;       // weight assigned when added
    double cumulativeProportion;     // recalculated later to between 0 and 1

    public Cmd (Command c, double proportion) {
      this.command = c;
      this.assignedProportion = proportion;
      this.cumulativeProportion = 0.0;
    }
  }

  // the list I'm using 
  private List<Cmd> commandDistribution = new ArrayList<Cmd>();
  private java.util.Random myRandom = new java.util.Random();

  void addCommand (Command command, double proportion) {
    commandDistribution.add ( new Cmd (command, proportion));
  }

  // ** MUST BE CALLED **, after adding all the commands, to normalise the proportions.
  // you could do this tidier by setting a flag in add, and checking it in
  // getNextCommandToExecute
  void normaliseProportion() {
    double total = 0;
    double cumulativeProp = 0;
    for (Cmd cmd: commandDistribution) {
       total += cmd.assignedProportion;
    }
    for (Cmd cmd: commandDistribution) {
       cumulativeProp += cmd.assignedProportion/total;
       cmd.cumulativeProportion = cumulativeProp;
    }
  }


  private Command getNextCommandToExecute () {
    double d = myRandom.nextDouble();
    for (Cmd cmd: commandDistribution) {
      if (d < cmd.cumulativeProportion) {
        return cmd.command;
      }
    }
    // theoretically, should not get here.  Never rely on theoretically.
    return commandDistribution.get(0).command;

  }

  public static void main (String [] args) {
    CommandDist cd = new CommandDist();
    Command c; 

    cd.addCommand (new Command ("A"), 50.0);
    cd.addCommand (new Command ("B"), 20.0);
    cd.addCommand (new Command ("C"), 15.0);
    cd.addCommand (new Command ("D"), 10.0);

    cd.normaliseProportion();


    for (int i = 0; i < 10000; i++) {
       c = cd.getNextCommandToExecute();
       c.execute();
    }

  }
}

出力は次のようになります。

Command: C
Command: A
Command: C
Command: A
Command: D

そして、一般的にこのように配布します(もちろん、実行ごとに異なるカウントです)。

java CommandDist | sort | uniq -c
   5183 Command: A
   2151 Command: B
   1595 Command: C
   1071 Command: D
于 2012-05-19T10:36:45.480 に答える