Fraction comparison trick

If you want to determine whether

a/b > c/d,

it is often enough to test whether

a+d > b+c.

Said another way a/b is usually greater than c/d when a+d is greater than b+c.

This sounds imprecise if not crazy. But it is easy to make precise and [1] shows that it is true.

Examples

Consider 4/11 vs 3/7. In this case 4 + 7 = 11 < 11 + 3 = 14, which suggests 4/11 < 3/7, which is correct.

But the rule of thumb can lead you astray. For example, suppose you want to compare 3/7 and 2/5. We have 3 + 5 = 8 < 7 + 2 = 9, but 3/7 > 2/5.

The claim isn’t that the rule always works; clearly it doesn’t. The claim is that it usually works, in a sense that will be made precise in the next section.

Rigorous statement

Let N be a large integer, and pick integers a, b, c, and d at random uniformly between 1 and N. Let

x = a/bc/d

and

y = (a+d) – (b+c).

Then the probability x and y are both positive, or both negative, or both zero, approaches 11/12 as N goes to infinity.

Simulation

I won’t repeat the proof of the theorem above; see [1] for that. But I’ll give a simulation that illustrates the theorem.

    import numpy as np
    
    np.random.seed(20210225)
    
    N = 1_000_000
    numreps = 10_000
    
    count = 0
    for _ in range(numreps):
        (a, b, c, d) = np.random.randint(1, N+1, 4, dtype=np.int64)
        x = a*d - b*c
        y = (a+d) - (b+c)
        if np.sign(x) == np.sign(y):
            count += 1
    print(count/numreps)

This prints 0.9176, and 11/12 = 0.91666….

The random number generator randint defaults to 32-bit integers, but this could lead to overflow since 106 × 106 > 232. So I used 64-bit integers.

Instead of computing a/bc/d, I multiply by bd and compute adbc instead because this avoids any possible floating point issues.

In case you’re not familiar with the sign function, it returns 1 for positive numbers, 0 for 0, and -1 for negative numbers.

The code suggests a different statement of the theorem: if you generate two pairs of integers, their sums and their products are probably ordered the same way.

Psychology

This post has assumed that the numbers a, b, c, and d are all chosen uniformly at random. But the components of the fractions for which you have any doubt whether a/b is greater or less than c/d are not uniformly distributed. For example, consider 17/81 versus 64/38. Clearly the former is less than 1 and the latter is greater than 1.

It would be interesting to try to assess how often the rule of thumb presented here is correct in practice. You might try to come up with a model for the kinds of fractions people can’t compare instantly, such as proper fractions that have similar size.

Related posts

[1] Kenzi Odani. A Rough-and-Ready Rule for Fractions. The Mathematical Gazette, Vol. 82, No. 493 (Mar., 1998), pp. 107-109

3 thoughts on “Fraction comparison trick

  1. How about [a/b>c/d] iff [(b·d)·(a·d)>(b·d)·(b·c)] for a,b,c,d integers and b and d nonzero?

    *Proof:* Since b and d are nonzero, their product is also nonzero and the square thereof is positive, so that [a/b>c/d] iff [(b·d)²·(a/b)>(b·d)²·(c/d)]. Rearranging factors leads to [a/b>c/d] iff [(b·d)·(a·d)>(b·d)·(b·c)]. No doubt your third-grader [I love you, you love me—just let’s stay Platonic, see?] can tweak this formula to make it easier given the argument.

  2. Jakub Kierzkowski

    If it works in 11 cases out of 12, I thought it was worth finding that 1 exceptional case out of 12 and looking at it. Maybe for such exceptions it would be possible to find another easy method or to detect them quickly?
    This pushed me toward a more combinatorial approach (I don’t like the statistical approach you’ve shown here).
    Instead of a force attack, I check all the interesting options one by one (although I generate these options randomly because I didn’t want to redo this part of the script –I’m not experienced in Python). But it’s also enlightening.
    I check Odani’s method for pairs of fractions in which both numerators are smaller than their denominators (if in one fraction the numerator is smaller and in the other the denominator is larger, the inequality is trivial, and if in both the numerators are larger, the algorithm works analogously as for the inverse). I omit duplicate pairs (if I take a,b,c,d, I do not take c,d,a,b).
    I increased N and observed the exceptions. Unfortunately, so far I haven’t observed much: in the exceptions I don’t see pairs of the form 1/b and 1/d (pretty obvious). It also seems that for many pairs for which Odani’s method does not work, a/b < 1/2 < c/d – but not for all of them. This should still be checked statistically.

    The number of the interesting pairs is nchoosek(nchoosek(N,2),2): for N=1e6 it's 1.25e23, much more than numreps you use.
    The efficiency I obtained is about 7/9 – to few to use the method, I think.

    Modified script:
    import numpy as np

    np.random.seed(20231107)

    N = 10
    numreps = 1_000_000

    numset = set()

    good, bad = 0, 0
    for _ in range(numreps):
    (a, b, c, d) = np.random.randint(1, N + 1, 4, dtype=np.int64)
    if a < b and c < d and (b < d or (b == d and a < c)):
    numset.add((a, b, c, d))

    # print(numset)
    total = len(numset)

    for (a, b, c, d) in numset:
    x = a * d – b * c
    y = (a + d) – (b + c)
    if np.sign(x) == np.sign(y):
    good += 1
    # print(a, b, c, d)
    else:
    bad += 1
    # print(a, b, c, d, "\t", x, y)
    print(good / total, bad, good, total)

Comments are closed.