Note that there are some explanatory texts on larger screens.

plurals
  1. PO
    primarykey
    data
    text
    <p>Let <code>p</code> be the percentage (the numerator, i.e. 25%), <code>x</code> by the initial value and <code>y</code> be the resulting integer.</p> <p>Since <code>p</code> is a percentage which is a multiple of 5 and from <code>0 to 100</code> then we can represent it as <code>p = 5a/100 = a/20</code> where <code>0 &lt;= a &lt;= 20</code>.</p> <p>For <code>x</code> we have the constraint that <code>100 &lt;= x &lt;= 999</code>.</p> <p>First pick an <code>a</code> that satisfies <code>0 &lt;= a &lt;= 20</code>.</p> <p>Next we pick an <code>x</code>. Well, for <code>p * x = (a/20) * x</code> to be an integer result we just need 20 to divide <code>a * x</code>. Well, we know that <code>20 | (a * x)</code> ("20 divides a * x") if and only if</p> <pre><code>j = (a * x) / 20 (&lt;- j is some integer) &lt;=&gt; j = (a * x) / (2^2 * 5^1) </code></pre> <p>Since we have <code>a</code> we can replace it by its prime factorization:</p> <pre><code>j = (p1^e1 * p2^e2 * ... * pn^en) * x / (2^2 * 5^1) </code></pre> <p>Now realize that <code>a</code> is less than 20 so it's prime factorization is probably pretty simple and likely to "overlap" with the prime factorization. For example, if <code>a = 5</code> then the above equation simplifies to</p> <pre><code>j = x / 4 </code></pre> <p>In which case it's easy to see how we can generate <code>x</code> that will produce an integer <code>j</code> (multiples of 4. Though you need <code>100 &lt;= x &lt;= 9999</code> too!). So "overlapping" (i.e. prime factors in the numerator which are the same as the denominator) are super beneficial. That's where the greatest common divisor comes into play. The <code>GCD(a, 20)</code> is the largest integer that divides both <code>a</code> and <code>20</code>. The prime factorization of the <code>GCD</code> is precisely the overlap. It also has the nice property that, once we "remove" the overlap, the resulting values:</p> <pre><code>j = b * x / c </code></pre> <p>Have the nice property that <code>b</code> and <code>c</code> are coprime. From that we know that <code>b * x / c</code> is an integer if and only if <code>c | x</code>.</p> <p>So let <code>GCD(a, 20) = k</code>. Then by definition we have <code>a/k = b</code> and <code>20/k = c</code>, so <code>a/20 = b/c</code>. Therefore let <code>x = c * m</code> where <code>m</code> is an integer. Then we have:</p> <pre><code>100 &lt;= m * c &lt;= 9999 =&gt; 100 / c &lt;= m &lt;= 9999 / c </code></pre> <p>So we can do a <code>floor(rand(100 / c, 9999 / c))</code> to produce your <code>m</code>.</p> <p>To summarize:</p> <pre><code>a = rand(0, 20) p = 5*a c = 20 / GCD(a, 20) m = floor(rand(100 / c, 9999 / c)) x = c * m y = (p / 100) * x </code></pre> <p>Note that <code>a = 0</code> is actually an edge case and furthermore, <code>floor()</code> won't give you a completely uniform distribution. If you need these to be covered I can probably think about it and tweak the answer a bit. Also, the euclidean algorithm is trivial to implement, you can look it up. Heck, since <code>a &lt; 20</code> you could probably just hardcode the function :)</p> <p><strong>edit</strong> I forgot to define <code>c</code> in my summary the first time through. Here's an example to produce the counter-example you had below:</p> <pre><code>a = 5 p = 25 c = 20 / GCD(5, 20) = 20 / 5 = 4 m = some integer in [25, 2500). In this case so we randomed 879 x = 3516 y = 879 </code></pre> <p>Conveniently in this example we have <code>GCD(a, 20) = 5</code> so it turns out that <code>m = y</code>, but that's not always the case.</p>
    singulars
    1. This table or related slice is empty.
    plurals
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. This table or related slice is empty.
    1. VO
      singulars
      1. This table or related slice is empty.
    2. VO
      singulars
      1. This table or related slice is empty.
 

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