Here's some intuition about why rand() * rand() is different than rand().
Let's say you are doing rand(2) which produces either 0 or 1, each equally often, then rand(2) * rand(2) will produce 0 much more often than 1.
0 * 0 = 0
0 * 1 = 0
1 * 0 = 0
1 * 1 = 1
Addition has a similar problem. 0 + 0 = 0
0 + 1 = 1
1 + 0 = 1
1 + 1 = 2
If you use the right range and wrap the result. e.g. if you do mod(rand(2^n) + rand(2^n), 2^n) then addition will not affect the distribution of your numbers.