3

In a project in which I'm working for, I'm required to either generate n random double numbers (depending from what the input file says) or converting them to doubles if I have them from my input file. Those numbers should have only 2 decimals after the comma (ex.: 0.98).

I know that in Java 8, there are 2 ways of doing this:

  1. Java 8 way: nthNumber = Double.parseDouble(new DecimalFormat("#.##").format(ThreadLocalRandom.current().nextDouble(0,1)).replace(",","."));
  2. Old fashion way: nthNumber = Double.parseDouble(new DecimalFormat("#.##").format(new Random().nextDouble()).replace(",", "."));

Asymptotically speaking, which is the fastest? From my poor knowledge of A.D.S., I'd say it would be the same time (O(n)?) but I'm not 100% sure

Aside from these two ways, are there any other ways to generate random doubles between 0 and 1 which are faster, asymptotically speaking, than my proposals? (rather, are there methods that can do everything in O(n) or O(1) ?)

Thank you in advance to everyone who will spend a minute to answer to this question of mine

Piotr Reszke
  • 1,576
  • 9
  • 21
Gianmarco F.
  • 780
  • 2
  • 12
  • 36
  • How about `Math.random()` – Bene Sep 13 '16 at 12:35
  • Is it faster than Random().nextDouble() or ThreadLocalRandom.current.nextDouble() ? – Gianmarco F. Sep 13 '16 at 12:36
  • 1
    You won't get any better than O(n) – xenteros Sep 13 '16 at 12:36
  • Duration of the actual function call has nothing to do with algorithmic complexity. You only need to use `ThreadLocalRandom` if this code will be executed concurrently on multiple threads. – vgru Sep 13 '16 at 12:39
  • @Groo from my really poor studies of A.D.S., I remember that the complexity of a function is given by the multiplication of the asymptotic cost of the various functions, that is why I'm talking about algorithmic complexity (but I may be wrong for sure) – Gianmarco F. Sep 13 '16 at 12:43
  • Possible duplicate of [What is a plain English explanation of "Big O" notation?](http://stackoverflow.com/questions/487258/what-is-a-plain-english-explanation-of-big-o-notation). Your random generator calculation does not depend on `N`, it only calculates a single random number at a time, meaning its complexity is `O(1)`. Multiply this with `N` and you get `O(N)` in both cases. Additionally, `ThreadLocalRandom` is just a per-thread instance of `Random`, so the same `Random.nextDouble()` is executed in both cases. – vgru Sep 13 '16 at 12:46
  • Take into account that one thing is the asymptotic complexity and another is the running time in seconds. Two different algorithms with the same asymptotic time can take different amount of seconds because of the hidden constants. I'm sure all the random number generators solutions have (more or less) the same asymptotic complexity, but you also have to consider actual running time if you want your program to run in a real world computer. – vz0 Sep 13 '16 at 12:49
  • Am I the only one with a Computer Science degree and still perplexed by the A.D.S. acronym? – Martin Spamer Sep 13 '16 at 13:26
  • @MartinSpamer it stands for Algorithm and Data Structures. – Gianmarco F. Sep 13 '16 at 13:54
  • @Groo and vz0 , thank you so much for your kind explanations! – Gianmarco F. Sep 13 '16 at 13:55

2 Answers2

11

Both of your approaches use strings as an intermediate representation, this will be quite inefficient (memory allocation, string parsing, string formatting are all relatively slow operations. You probably also want to avoid allocating multiple instances of Random.

Given that you only want two decimal digits, why not create an integer in the range of 0..99 and divide it by 100.0?

Random random = new Random();  // Only one instance needed.
for (int n = 0; n < total; n++) {
   double nthRandomNumber = random.nextInt(100) / 100.0;
}
Piotr Reszke
  • 1,576
  • 9
  • 21
Stefan Haustein
  • 18,427
  • 3
  • 36
  • 51
  • You are absolutely right Stefan, I never thought about this approach for generating random numbers! I'm doing all of that complicated stuff because, some times, I may have the values I need from the input file – Gianmarco F. Sep 13 '16 at 13:57
  • Don't you think that if the number of digits (precision) is important, then using Double is not advised? – Piotr Reszke Sep 13 '16 at 15:57
  • @PiotrR This project forces me to work with Doubles, so I can't use Float – Gianmarco F. Sep 13 '16 at 21:22
1

Your code looks complicated.

Did you consider the following:

DecimalFormat decimalFormat = new DecimalFormat("0.00");
String twoDigitRandom = decimalFormat.format(Math.random());

Reference: https://docs.oracle.com/javase/7/docs/api/java/lang/Math.html#random()

Returns a double value with a positive sign, greater than or equal to 0.0 and less than 1.0.

Edit: Added after the comment:

If you would like to control the number of digits and not to have a String as end result, then I would advise not to use Double, try BigDecimal instead:

MathContext m = new MathContext(3);
BigDecimal randomWithTwoDigits = new BigDecimal(Math.random(), m);
Piotr Reszke
  • 1,576
  • 9
  • 21
  • I need a double, that's why I'm doing all that complicated stuff and the parseDouble – Gianmarco F. Sep 13 '16 at 13:56
  • Ok, I've added a second option. BigDecimal is more natural if you want to control the number of digits. – Piotr Reszke Sep 13 '16 at 15:56
  • The second function with BigDecimal returns 4 decimal once out of 10. When the first decimal is 0, it returns a number like this : 0.0145 I imagine that if the two first decimal is 0, it returns a number like this : 0.00145 – Jeff Dec 30 '22 at 07:54