# Fraction practice sheet

January 5, 2011 at 10:57 PM by Dr. Drang

I had a long drive today, and I passed the time by thinking about making a new set of math practice sheets for my ten-year-old son. This year has been fraction-heavy, so I thought I’d start with a simple one: a page with a bunch of proper fractions that may or may not need to be reduced to lowest terms.

It’s like all my other math worksheets, an HTML page that generates a new set of problems every time you open or refresh the page. The numbers are big, easy to read, and have enough space around them for the intermediate work. I don’t give the answers—that’s for you and your child to figure out, together or separately.

All the HTML, JavaScript, and CSS are together in one file. You can either access the page online or download it to your hard disk and open it from there. Feel free to modify it to fit your needs, but please don’t delete the attribution near the top of the file.

Here’s the code itself:

```
html:
1: <!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
2: "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
3: <html>
4: <!--
5: A math practice sheet for reducing fractions to lowest terms.
6: Released under the Creative Commons Attribution-Share Alike 3.0
7: Unported License (http://creativecommons.org/licenses/by-sa/3.0/)
8: by Dr. Drang (http://www.leancrew.com).
9: -->
10: <head>
11: <title>Reducing Fractions</title>
12: <style type="text/css">
13: h1 {
14: text-align: center;
15: font-family: Sans-Serif;
16: font-weight: bold;
17: font-size: 36px;
18: margin-top: 40px;
19: padding: 0;
20: }
21: #whole {
22: margin-left: auto;
23: margin-right: auto;
24: }
25: table.problem {
26: font-family: Sans-Serif;
27: font-size: 24px;
28: text-align: center;
29: width: 40px;
30: margin: 50px;
31: }
32: td.numerator {
33: border-bottom: solid;
34: }
35: </style>
36:
37: <script type="text/javascript">
38: // GCD of two positive integers.
39: function gcd(a, b) {
40: if (b > a) {
41: var temp = a; a = b; b = temp;
42: }
43: while (true) {
44: a %= b;
45: if (a == 0) return b;
46: b %= a;
47: if (b == 0) return a;
48: }
49: return b;
50: }
51:
52: // Return all numerators of reduced fractions with given denominator.
53: function numerators(d) {
54: var p = [];
55: for (var i=1; i<d; i++) {
56: p.push(i);
57: }
58: var n = p.filter(function(e, i, a) {
59: return gcd(e, d) == 1;
60: });
61: return n;
62: }
63:
64: // Return all reduced fractions with denominators up through the
65: // given value. Result will be a list of lists.
66: function fractions(denoms) {
67: f = [];
68: for (var j=0; j<denoms.length; j++) {
69: var n = numerators(denoms[j]);
70: for (var i=0; i<n.length; i++) {
71: f.push([n[i],denoms[j]]);
72: }
73: }
74: return f;
75: }
76:
77: // Generate all the reduced fractions.
78: var allReduced = fractions([2,3,4,5,6,7,8,9,10,12]);
79:
80: // The HTML for a single problem.
81: function singleProblem() {
82: var maxMultiplier = 12;
83: var pick = Math.floor(Math.random()*allReduced.length);
84: var multiplier = Math.floor(Math.random()*maxMultiplier) + 1;
85: var num = multiplier*allReduced[pick][0];
86: var denom = multiplier*allReduced[pick][1];
87: return '<table class="problem">' +
88: '<tr><td class="numerator">' + num + '</td></tr>' +
89: '<tr><td>' + denom + '</td></tr>' +
90: '</table>';
91: }
92:
93: </script>
94: </head>
95: <body>
96: <h1>Reducing Fractions</h1>
97: <table id="whole">
98: <script>
99: for (i=0; i<5; i++){
100: document.write("<tr>");
101: for (j=0; j<5; j++) {
102: document.write('<td>' + singleProblem() + '</td>');
103: }
104: document.write('</tr>');
105: }
106: </script>
107: </table>
108: </body>
109: </html>
```

The basic idea is simple. For each problem, the `singleProblem function (Lines 81-91) selects a proper fraction in lowest terms, multiplies it by a random integer, and generates the HTML for displaying it on the sheet.

Where does `singleProblem`

get the list of fractions to pick from? That’s the job of the `fractions`

function, which is defined on Lines 66-75 and called on Line 78. It generates an array of all possible proper fractions in lowest terms for a given list of denominators. For example, if we gave it the list `[2, 3, 4, 5, 6]`

, it would return the list of lists

```
[1, 2]
[1, 3], [2, 3]
[1, 4], [3, 4]
[1, 5], [2, 5], [3, 5], [4, 5]
[1, 6], [5, 6]
```

where each sublist is a [numerator, denominator] pair. Note that pairs like `[2, 4]`

and `[4, 6]`

are not returned, as these are not in lowest terms. These pairs are filtered out of the results by making sure that the numerator and denominator are relatively prime. The filtering is done through the `gcd`

function in Lines 39-50. If the greatest common divisor of two numbers is one, they’re relatively prime. The `gcd`

function uses Euclid’s Algorithm and is a slight adaptation of this one by Robert Campbell of the University of Maryland, Baltimore County.

I chose to generate fractions with denominators of 2 through 12, excluding 11. I wanted the answers to be fairly simple but not restricted to single-digit denominators. Twelve seemed like a good upper limit. I decided to exclude 11 from the list of possible denominators because if I hadn’t it would have dominated the answers. Recall that 11 is prime, so there are 10 proper fractions in lowest terms with 11 as the denominator—far more than any of the other denominators I was using. Because `singleProblem`

makes a uniform random choice from among the list of possible fractions, leaving 11 in the list would have meant that it would be the denominator in nearly one-fourth of the answers, which just didn’t seem right.

The multiplier—the number that “unreduces” the fractions—is chosen at random for each problem and can be any integer in the range 1-12, inclusive. Note that this means that some fractions on the sheet will multiplied by 1 and will therefore already be in lowest terms. These are meant to keep your student on his or her toes.

I’ve tested the page in Firefox, Google Chrome, and Safari, and it works for me. Let me know if you have any problems with it. Screenshots and error messages are appreciated when debugging.