Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    text
    copied!<p>As several comments have mentioned, these two requirements conflict with each other:</p> <blockquote> <p>I want to generate a random number between -1000 and 1000</p> </blockquote> <p>and</p> <blockquote> <p>the numbers generated should fall in a standard normal distribution with an average of x</p> </blockquote> <p>because a standard <a href="http://en.wikipedia.org/wiki/Normal_distribution" rel="nofollow">normal distribution</a> has an infinite domain. If you choose numbers from a normal distribution, there will be some probability that you get a value greater than 1000 or less than -1000. Conversely, if you do anything to limit the range to [-1000,1000], then you will not be drawing from a normal distribution.</p> <p>One option is to generate numbers according to a truncated normal distribution, which is just like a standard normal distribution except that the probability is set to zero outside the range [-1000,1000]. The easiest way to do this is to pick a number according to a normal distribution, and if it's outside the desired range, just pick again.</p> <pre><code>SIGMA=10.0 # you can pick this value to be pretty much anything def generate_number(average): x = random.normal_variate(average, SIGMA) while x &gt; 1000 or x &lt; -1000: x = random.normalvariate(average, SIGMA) return x </code></pre> <p>Here <code>SIGMA</code> is the standard deviation of the normal distribution, which governs how spread out the values will be. If <code>SIGMA</code> is small and <code>average</code> is not close to 1000 or -1000, or to be precise: if <code>(1000-average)/SIGMA</code> and <code>(1000+average)/SIGMA</code> are both larger than 2 or 3, then this method will be fairly efficient because it will usually hit a number within the desired range [-1000,1000] the first time. But if one of those ratios is small, like around 1 or less, then the algorithm will sometimes have to loop once or twice. That probably won't be a big deal. (If you wanted to avoid it there are advanced techniques you could use, but I don't think it'd be worth the complexity.)</p> <p>Another option, which is kind of what your example code in the question does, is to drop the requirement of using a normal distribution entirely, and use some other probability distribution which is naturally restricted to a certain range. Your example code, equivalent to</p> <pre><code>random.triangular(-1000,1000,mode) </code></pre> <p>uses a distribution in which the probability increases linearly from -1000 to the <code>mode</code> and then decreases linearly from <code>mode</code> to 1000. The catch with this, though, is that <code>mode</code> is the value which has the largest probability of being chosen. It's not the same as the average of the numbers chosen. The actual average is <code>(min+max+mode)/3.</code>, or in your case, since <code>min+max = 1000-1000 = 0</code>, just <code>mode/3</code>, so if you wanted to generate numbers with a specified average, you would have to use</p> <pre><code>def generate_number(average): mode = 3*average if mode &lt; -1000 or mode &gt; 1000: raise ValueError('Average cannot be satisfied: %f' % average) return random.normal_variate(-1000, 1000, mode) </code></pre> <p>Note that using this distribution means you can never produce numbers with an average less than <code>-1000./3.</code> or greater than <code>1000./3.</code>, unless you also adjust the min or max values accordingly.</p>
 

Querying!

 
Guidance

SQuiL has stopped working due to an internal error.

If you are curious you may find further information in the browser console, which is accessible through the devtools (F12).

Reload