1

I am using a Matlab built-in function rand in an algorithm to generate non-zero elements. It is explained that the function rand should produce a real number in the open interval (0,1). However, when I run the code, I get zero in most of the elements. Let me explain the code: there is a for loop. In each iteration, I am trying to multiply a random number with a certain variable that is subtracted by the multiplication of the same variable with another random number from the previous iteration. So by math, the variable approaches to zero, but it cannot be zero. Can you give me a suggestion about why it is happening? If convenient, can you recommend a way to avoid this?

For your information, I put the algorithm below. The variable which will decay at each iteration is Volume. The desired output is collected at the variable frag.

numbofprogeny = 2000;
Volume = 1;
frag = zeros(1,numbofprogeny);
for i=1:numbofprogeny
  frag(i) = Volume*rand;
  Volume = Volume-frag(i);
end
Cris Luengo
  • 55,762
  • 10
  • 62
  • 120

1 Answers1

4

The problem is not with the rand function but float underflow.

Consider the following simplified code:

v = 1000;
n = 1000;
for i = 1:n
    v = v * rand;
    disp(v);
end;

Every iteration, v is multiplied by a random number (0,1). As a result it keeps getting smaller until it is too small to be represented, and becomes "0", even though mathematically speaking it should be a tiny but non-zero number.

Junuxx
  • 14,011
  • 5
  • 41
  • 71
  • Thank you very much, that is really informative. Also, I assume that it is inevitable unless the precision is lost. – Mahmut Camalan Jan 06 '20 at 20:31
  • 1
    One solution could be to use the [vpa function](https://www.mathworks.com/help/symbolic/increase-precision-of-numeric-calculations.html). See [here](https://stackoverflow.com/questions/33003470/how-to-deal-with-overflow-and-underflow) for some additional suggestions. But it might be worth reconsidering your approach altogether. – Junuxx Jan 06 '20 at 20:43
  • @MahmutCamalan: The way to avoid underflow is to multiply by a number in a smaller random range, for example `frag(i) = Volume*rand*0.01`. This way the progression is slower and it takes a lot longer to get too close to zero volume. – Cris Luengo Jan 06 '20 at 20:54
  • 1
    @Junuxx vpa worked pretty well; however, the values are stored as symbolic type. – Mahmut Camalan Jan 06 '20 at 21:22
  • @CrisLuengo your suggestion also worked pretty well. How about using `rand`*`rand` ? – Mahmut Camalan Jan 06 '20 at 21:24