简体   繁体   中英

Programming structure style when writing probablistic algorithms

I have this kind of program structure for choosing at random program execution. However this style is not extendable, maintainable and very error prone. as you can see the condition of the if statements are getting long and unreadable

Can you suggest a better programming style / structure ?

double aProb = 0.4;

double bProb = 0.2;

double cProb = 0.2;

double dProb = 0.2;

double chance = random.nextDouble();

if ( chance < aProb ) {
    a();
}

if ( chance < bProb + aProb ) {
    b();
}

if ( chance < cProb + bProb + aProb ) {
    c();
}

if ( chance < dProb + cProb + bProb + aProb ) {
    d();
}

I think it's clear.

If you want shorter,

double chance = random.nextDouble();

if ((chance -= 0.4) < 0) {
    a();
} else if ((chance -= 0.2) < 0) {
    b();
} else if ((chance -= 0.2) < 0) {
    c();
} else {
    d();
}

(I assume you wanted else if .)

您可以创建一个存储aProb + bProb的新变量,该变量在除第一个语句之外的每个if语句中都会使用,这会使它变短。

You may create class abstract class IntervalAction :

public abstract class IntervalAction {

    private final double minBound;
    private final double maxBound;

    public IntervalAction(double minBound, double maxBound) {
        if (minBound < 0) throw new IllegalArgumentException("minBound >= 0");
        if (maxBound > 1) throw new IllegalArgumentException("maxBound <= 0");
        if (minBound > maxBound) throw new IllegalArgumentException("maxBound >= minBound");

        this.minBound = minBound;
        this.maxBound = maxBound;
    }

    public abstract void execute();

    @Override
    public String toString() {
        return "IntervalAction{" +
                "minBound=" + minBound +
                ", maxBound=" + maxBound +
                '}';
    }
}

and registry class which will have all available actions:

public class ActionRegistry {

    public void register(IntervalAction action) {
        if (intersectsWithExistingRange(action))
            throw new IllegalArgumentException("Already have action in that range: " + action);

        // todo registration in internal data structure
    }

    private boolean intersectsWithExistingRange(IntervalAction action) {
        // todo
        return true;
    }

    public void execute(double input) {
        IntervalAction action = find(input);
        if (action == null) throw new IllegalArgumentException("No action found for " + input);
        action.execute();
    }

    private IntervalAction find(double input) {
        // todo
        return null;
    }
}

And a driver class:

public class ActionDriver {
    private final ActionRegistry registry;
    private final Random random;


    public ActionDriver() {
        random = new Random(System.currentTimeMillis());

        registry = new ActionRegistry();
        registry.register(new IntervalAction(0, 0.1) {
            @Override
            public void execute() {
                System.out.println(this);
            }
        });
        registry.register(new IntervalAction(0.1, 0.2) {
            @Override
            public void execute() {
                System.out.println(this);
            }
        });
        // so on
    }


    public void act() {
        registry.execute(random.nextDouble());
    }
}

Now, the most interesting part is how can you implement internal data structure in ActionRegistry to hold (and search for) your actions -- all of these todos in above code sample. For that I'll refer you to this SO question.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM