0

To make sure that this is not a duplicate, I have already checked this and this out.

I want to generate random numbers in a specific range including step size (not continuous distribution).

For example, I want to generate random numbers between -2 and 3 in which the step between two consecutive numbers is 0.02. (e.g. [-2 -1.98 -1.96 ... 2.69 2.98 3] so a generated number should be 2.96 not 2.95).

I have tried this:

a=-2*100;
b=3*100;
r = (b-a).*rand(5,1) + a;
for i=1:length(r)
    if r(i) >= 0
        if mod(fix(r(i)),2)
            r(i)=ceil(r(i))/100;
        else
            r(i)=floor(r(i))/100;
        end
    else
        if mod(fix(r(i)),2)
            r(i)=floor(r(i))/100;
        else
            r(i)=ceil(r(i))/100;
        end
    end
end

and it works.

there is an alternative way to do this in MATLAB which is :

y = datasample(-2:0.02:3,5,'Replace',false)

I want to know:

  1. How can I make my own implementation faster (improve the performance)?
  2. If the second method is faster (it looks faster to me), how can I use similar implementation in C++?
Community
  • 1
  • 1
NKN
  • 6,482
  • 6
  • 36
  • 55

2 Answers2

2

Those previous answers do cover your case if you read carefully. For example, this one produces random numbers between limits with a step size of one. But let's generalize this to an arbitrary step size in case you can't figure out how to get there. There are several different ways. Here's one using randi where we use the default step size of one and the range from one to the number possible values as indices:

lo = 2;
hi = 3;
step = 0.02;
v = lo:step:hi;
r = v(randi(length(v),[5 1]))

If you look inside datasample (type edit datasample in your command window to view the code) you'll see that it's doing something very similar to this answer. In the case of the 'Replace' option being true see around line 135 (in R2013a at least).

If the 'Replace' option is false, as in your use of datasample above, then randperm actually needs to be used instead (see around line 159):

lo = 2;
hi = 3;
step = 0.02;
v = lo:step:hi;
r = v(randperm(length(v),51))

Because there is no replacement in this case, 51 is the maximum number of values that can be requested in a call and all values of r will be unique.

In C++ you should not use rand() if you're doing scientific computing and generating large numbers of random variates. Instead you should use a large period random number generator such as Mersenne Twister (the default in Matlab). C++11 includes a version of this generator as part of . More here in rand(). If you want something fast, you should try the Double precision SIMD-oriented Fast Mersenne Twister. You'll have to ask another question if you want to implement your code in C++.

Community
  • 1
  • 1
horchler
  • 18,384
  • 4
  • 37
  • 73
1

The distribution you want is a simple transform of integers, so how about:

step = 0.02
r = randi([-2 3] / step, [5, 1]) * step;

In C++, rand() generates integers too, so it should be pretty obvious how to take a similar approach there.

Notlikethat
  • 20,095
  • 3
  • 40
  • 77