2

I have 2 strings in an array. I want there to be a 10% chance of one and 90% chance to select the other. Right now I am using:

Random random = new Random();
int x = random.nextInt(100 - 1) + 1;
if (x < 10) {
    string = stringArray(0);
} else {
    string = stringArray(1);
}

Is this the best way of accomplishing this or is there a better method?

Ferdz
  • 1,182
  • 1
  • 13
  • 31
th3ramr0d
  • 484
  • 1
  • 7
  • 23
  • 2
    You could do something like `string = stringArray(x < 10 ? 0 : 1)`, but "better" is subjective. – Carcigenicate Mar 07 '19 at 16:40
  • 1
    What's wrong with that? Although just doing 0-9 would be just as good. IIRC there are also libraries that will handle things like this, but I can't remember if the ones I used were Java or something else. But I'm sure there are weighted libs out there. – Dave Newton Mar 07 '19 at 16:43
  • Instead of `new Random()` consider using `ThreadLocalRandom.current()`. – Klitos Kyriacou Mar 07 '19 at 18:03

2 Answers2

4

I know it's typically a bad idea to submit a stack overflow response without submitting code, but I really challenge this question of " the best way." People ask this all the time and, while there are established design patterns in software worth knowing, this question almost always can be answered by "it depends."

For example, your pattern looks fine (I might add some comments). You might get a minuscule performance increase by using 1 - 10 instead of 1 - 100, but the things you need to ask yourself are as follows :

  1. If I get hit by a bus, is the person who is going to be working on the application going to know what I was trying to do?
  2. If it isn't intuitive, I should write a comment. Then I should ask myself, "Can I change this code so that a comment isn't necessary?"
  3. Is there an existing library that solves this problem? If so, is it FOSS approved (if applicable) / can I use it?
  4. What is the size of this codebase eventually going to be? Am I making a full program with microservices, a DAO, DTO, Controller, View, and different layers for validation?
  5. Is there an existing convention to solve my problem (either at my company or in general), or is it unique enough that I can take my own spin on it?
  6. Does this follow the DRY principle?

I'm in (apparently) a very small camp on stack overflow that doesn't always believe in universal "bests" for solving code problems. Just remember, programming is only as hard as the problem you're trying to solve.

EDIT Since people asked, I'd do it like this:

/*
 * @author  DaveCat
 * @version 1.0
 * @since   2019-03-9 
 * Convenience method that calculates 90% odds of A and 10% odds of B.
 *
 */
    public static String[] calculatesNinetyPercent()
    {
        Random random = new Random();
        int x = random.nextInt(10 - 1 ) + 1
        //Option A
        if(x <= 9) {
            return stringArray(0);
        }
        else
        {
        //Option B
            return stringArray(1);
        }
    }

As an aside, one of the common mistakes junior devs make in enterprise level development is excessive comments.This has a javadoc, which is probably overkill, but I'm assuming this is a convenience method you're using in a greater program.

Edit (again)

You guys keep confusing me. This is how you randomly generate between 2 given numbers in Java

DaveCat
  • 773
  • 1
  • 10
  • 28
  • 1
    I really liked your answer, but you didn't finished your reasoning. Can you provide an answer that aproximate to the best one? – R. Karlus Mar 07 '19 at 17:35
  • 1
    Yes, it was close. Actually, it would be better to use a Math.random() without sub or add anything. First because Math.random() has a greatest distribution. Second because you don't need so much variables. I'll vote up your answer because I really like the way you see it all, but I'm going to answer too, not supposing, of course, that my answer would be accepted since you've said everything that have to be said. – R. Karlus Mar 07 '19 at 17:50
  • I preferred without code: it's wrong - with `<=` you will get 100% of `[0]`; with `<` (before edit) 89% (8/9). You need `nextInt(10)` [numbers between 0(included) and 10(**excluded**)] to get 90%/10% – user85421 Mar 07 '19 at 17:54
  • 1
    still wrong, author needs (as I understand) 10%/90% - your code is returning 11%/89% - `nextInt(9)` is returning numbers between 0 and 8, that is **nine** numbers, not ten – user85421 Mar 07 '19 at 18:05
  • 1
    I know you added just a quick code snippet to support your (valid) arguments, but please check it in an IDE, make the javadoc match the signature (what are A and B?), and have a look at the indentation. – Ralf Kleberhoff Mar 07 '19 at 18:11
  • `10 - 1 + 1`? Why? – Dave Newton Mar 07 '19 at 19:08
0

One alternative is to use a random float value between 0..1 and comparing it to the probability of the event. If the random value is less than the probability, then the event occurs.

In this specific example, set

x
to a random float and compare it to
0.1

I like this method because it can be used for probabilities other than percent integers.

levis501
  • 4,117
  • 23
  • 25
  • 1
    Have you vetted that assumption via testing on a specific implementation? Java's RNGs are reasonably uniform (within the bounds of how it's generating the bits in the first place); I doubt the "amount of randomness" is significantly different whether or not you're generating floats or ints. If you have a reference I'd like to read it. The docs of `nextInt` discuss this but don't provide a mathematical reference. – Dave Newton Mar 07 '19 at 17:07
  • 1
    Java's integer generator [explicitly uses a rejection scheme to avoid bias](https://docs.oracle.com/javase/8/docs/api/index.html?overview-summary.html) from the pigeonhole principle. And independence is an absolute property of distribution functions, regardless of the number of outcomes - you either have it, or you don't, period. If the joint distribution is equal to the product of the marginals for all outcomes, you have independence no matter how many outcomes there are. – pjs Mar 07 '19 at 17:21
  • I've removed the statistical claim as I cannot substantiate atm. Thanks daveNewton and pjs . For anyone following along later, the claim was: "Also, limiting the range of values to an integer [1,100] reduces the randomness of the generator. A float from 0 to 1 has more possible values than 100, allowing more independence between the values." – levis501 Mar 07 '19 at 17:47