<?xml version="1.0" encoding="UTF-8"?>
<rss version="2.0" xmlns:atom="http://www.w3.org/2005/Atom" xmlns:dc="http://purl.org/dc/elements/1.1/">
  <channel>
    <title>Forem: Payam Bijeh</title>
    <description>The latest articles on Forem by Payam Bijeh (@pibyte).</description>
    <link>https://forem.com/pibyte</link>
    <image>
      <url>https://media2.dev.to/dynamic/image/width=90,height=90,fit=cover,gravity=auto,format=auto/https:%2F%2Fdev-to-uploads.s3.amazonaws.com%2Fuploads%2Fuser%2Fprofile_image%2F3781821%2F36945beb-d730-454b-b766-5d0f7b8541b5.jpg</url>
      <title>Forem: Payam Bijeh</title>
      <link>https://forem.com/pibyte</link>
    </image>
    <atom:link rel="self" type="application/rss+xml" href="https://forem.com/feed/pibyte"/>
    <language>en</language>
    <item>
      <title>Modulo Bias Error</title>
      <dc:creator>Payam Bijeh</dc:creator>
      <pubDate>Fri, 20 Feb 2026 01:55:07 +0000</pubDate>
      <link>https://forem.com/pibyte/modulo-bias-error-1g57</link>
      <guid>https://forem.com/pibyte/modulo-bias-error-1g57</guid>
      <description>&lt;p&gt;When I wrote a random function in C, based on the high number of program iterations, I noticed that certain states occurred more frequently, even though I was seeding the &lt;code&gt;rand()&lt;/code&gt; function based on time. Later, I realized the problem was with my own calculations; the way I had written the code suffered from "Modulo Bias," which caused some outcomes to have a higher probability!&lt;/p&gt;

&lt;p&gt;The &lt;code&gt;rand()&lt;/code&gt; function generates a positive number in the range &lt;code&gt;[0, RAND_MAX]&lt;/code&gt;, so the range length is &lt;code&gt;RAND_MAX + 1&lt;/code&gt;. The first code, which contains the Modular Bias error, looks like this:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;rng_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;()&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Assume RAND_MAX is a very small number like 15. In this case, if I want random numbers from the range &lt;code&gt;[0, 5]&lt;/code&gt;, since my range length is 6, that larger range of 0 to 15 must be mapped onto the numbers 0 to 5 to get my desired result. (For example, if the function gives me 13, I don't want it because it's not in the 0-5 range, so I map it to the number 1). Now, for all outputs from 0 to 15 of rand(), this is what happens:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;0 % 6 = 0     1 % 6 = 1
2 % 6 = 2     3 % 6 = 3
4 % 6 = 4     5 % 6 = 5
6 % 6 = 0     7 % 6 = 1
8 % 6 = 2     9 % 6 = 3
10 % 6 = 4    11 % 6 = 5
12 % 6 = 0    13 % 6 = 1
14 % 6 = 2    15 % 6 = 3
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Did you notice? The numbers &lt;code&gt;{0,1,2,3}&lt;/code&gt; are repeated | mapped 3 times, while the numbers &lt;code&gt;{4,5}&lt;/code&gt; are only repeated | mapped 2 times!We fix this error here using the rejection sampling method with a do while loop:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight c"&gt;&lt;code&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="nf"&gt;rng_int&lt;/span&gt;&lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt;&lt;span class="p"&gt;,&lt;/span&gt; &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;max&lt;/span&gt;&lt;span class="p"&gt;){&lt;/span&gt;
    &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;max&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="mi"&gt;1&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="kt"&gt;unsigned&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;RAND_MAX&lt;/span&gt; &lt;span class="o"&gt;-&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;RAND_MAX&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="kt"&gt;int&lt;/span&gt; &lt;span class="n"&gt;random&lt;/span&gt;&lt;span class="p"&gt;;&lt;/span&gt;
    &lt;span class="k"&gt;do&lt;/span&gt; &lt;span class="p"&gt;{&lt;/span&gt;
       &lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;=&lt;/span&gt; &lt;span class="n"&gt;rand&lt;/span&gt;&lt;span class="p"&gt;();&lt;/span&gt;
    &lt;span class="p"&gt;}&lt;/span&gt; &lt;span class="k"&gt;while&lt;/span&gt;&lt;span class="p"&gt;((&lt;/span&gt;&lt;span class="kt"&gt;unsigned&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;&amp;gt;=&lt;/span&gt; &lt;span class="n"&gt;limit&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
    &lt;span class="k"&gt;return&lt;/span&gt; &lt;span class="n"&gt;min&lt;/span&gt; &lt;span class="o"&gt;+&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="n"&gt;random&lt;/span&gt; &lt;span class="o"&gt;%&lt;/span&gt; &lt;span class="p"&gt;(&lt;/span&gt;&lt;span class="kt"&gt;int&lt;/span&gt;&lt;span class="p"&gt;)&lt;/span&gt;&lt;span class="n"&gt;range&lt;/span&gt;&lt;span class="p"&gt;);&lt;/span&gt;
&lt;span class="p"&gt;}&lt;/span&gt;
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;What happened? With the limit variable, we equalized everyone's chances. The limit value is the largest number in the range &lt;code&gt;[0, RAND_MAX]&lt;/code&gt; that is perfectly divisible by our desired range length. In our example, limit equals 12; within the &lt;code&gt;do while&lt;/code&gt; loop, we ensure that if the output isn't within the range &lt;code&gt;[0, limit - 1]&lt;/code&gt;, it gets re-selected so that everyone's chances stay equal.&lt;/p&gt;

&lt;p&gt;Ultimately, what exactly is Modulo Bias? Well, Modulo (with that cute pronunciation) is just the % operator, and in the world of probability, the weighting of probability toward one side when everyone is expected to have an equal chance is called Bias—like when one side of a coin is heavier than the other.&lt;/p&gt;

&lt;p&gt;&lt;strong&gt;Digging Deeper:&lt;/strong&gt;&lt;br&gt;
The value of RAND_MAX in current implementations is &lt;code&gt;2,147,483,647&lt;/code&gt;.&lt;br&gt;
You can find this by running the following commands in a bash terminal:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight shell"&gt;&lt;code&gt;&lt;span class="nb"&gt;echo&lt;/span&gt; &lt;span class="s1"&gt;'#include &amp;lt;stdio.h&amp;gt;
#include &amp;lt;stdlib.h&amp;gt;
int main(){ printf("%d\n", RAND_MAX); }'&lt;/span&gt; | gcc &lt;span class="nt"&gt;-x&lt;/span&gt; c - &lt;span class="o"&gt;&amp;amp;&amp;amp;&lt;/span&gt; ./a.out

&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might think to yourself that this probabilistic inequality occurred only because we assumed a small RAND_MAX in our example. (We call it "probabilistic" because if the larger range to be mapped happens to be an exact multiple of our target range, all probabilities are distributed equally). Well, let's assume its value is &lt;code&gt;2,147,483,647&lt;/code&gt; and we want to map it onto the range &lt;code&gt;[0, 5]&lt;/code&gt;:&lt;/p&gt;

&lt;p&gt;First, let's find the lengths of the ranges:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mapped Range = 2,147,483,647 + 1 = 2,147,483,648 (which is $2^{31}$)
Mapping Range = 6
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of integer division tells us the minimum number of times each number inside the range is mapped:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mapped Range / Mapping Range = 357,913,941
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;The result of the modulo operator tells us that the first two numbers of our target range are mapped one extra time, so they get one more chance! (In fact, it's always these initial numbers of the range that might get the extra chance).&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mapped Range % Mapping Range = 2
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;Thus, we conclude:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;{2,3,4,5} are mapped 357,913,941 times
{0,1} are mapped 357,913,942 times

TRUTH CHECK:$4 \times 357,913,941 + 2 \times 357,913,942 = 2,147,483,648$ (The full Mapped Range!)
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;You might say, "See? Since the probabilities are so close in such a large range, one extra chance doesn't even get noticed; our point was right." Even if it's not noticeable, the chances are still not equal. But you're right—it's barely worth writing a few extra lines of code. However, let's increase the range we want for random number generation and see if it's still "not worth it." This time, let our target range be &lt;code&gt;[0, 999999]&lt;/code&gt;. Repeating the steps above:&lt;br&gt;
&lt;/p&gt;

&lt;div class="highlight js-code-highlight"&gt;
&lt;pre class="highlight plaintext"&gt;&lt;code&gt;Mapped Range = 2,147,483,648
Mapping Range = 1,000,000
Mapped Range / Mapping Range = 2,147
Mapped Range % Mapping Range = 483,648
&lt;/code&gt;&lt;/pre&gt;

&lt;/div&gt;



&lt;p&gt;In simple terms, what kind of justice is this, where the first &lt;code&gt;483,648&lt;/code&gt; numbers of the range have an extra chance in a range that only has a million numbers in total?&lt;/p&gt;

&lt;p&gt;🖤 - PiBytes&lt;/p&gt;

</description>
      <category>c</category>
      <category>algorithms</category>
      <category>programming</category>
      <category>tutorial</category>
    </item>
  </channel>
</rss>
