contextFraction.pl - Implements a MathObject class for Fractions.
This context implements a Fraction object that works like a Real, but keeps the numerator and denominator separate. It provides methods for reducing the fractions, and for allowing fractions with a whole-number preceding it, as in 4 1/2 for "four and one half". The answer checker can require that students reduce their results, and there are contexts that don't allow entery of decimal values (only fractions), and that don't allow any operators or functions (other than division and negation).
To use these contexts, first load the contextFraction.pl file:
loadMacros("contextFraction.pl");
and then select the appropriate context -- one of the following:
Context("Fraction");
Context("Fraction-NoDecimals");
Context("LimitedFraction");
Context("LimitedProperFraction");
The first is the most general, and allows fractions to be intermixed with real numbers, so 1/2 + .5 would be allowed. Also, 1/2.5 is allowed, though it produces a real number, not a fraction, since this fraction class only implements fractions of integers. All operators and functions are defined, so there are no restrictions on what is allowed by the student.
The second does not allow decimal numbers to be entered, but they can still be produced as the result of function calls, or by named constants such as "pi". For example, 1/sqrt(2) is allowed (and produces a real number result). All functions and operations are defined, and the only real difference between this and the previous context is that decimal numbers can't be typed in explicitly.
The third context limits the operations that can be performed: in addition to not being able to type decimal numbers, no operations other than division and negation are allowed, and no function calls at all. Thus 1/sqrt(2) would be illegal, as would 1/2 + 2. The student must enter a whole number or a fraction in this context. It is also permissible to enter a whole number WITH a fraction, as in 2 1/2 for "two and one half", or 5/2.
The fourth is the same as LimiteFraction, but students must enter proper fractions, and results are shown as proper fractions.
You can use the Compute() function to generate fraction objects, or the Fraction() constructor to make one explicitly. For example:
Context("Fraction");
$a = Compute("1/2");
$b = Compute("4 - 1/6");
$c = Compute("(4/9)^(1/2)");
Context("LimitedFraction");
$d = Compute("4 2/3");
$e = Compute("-1 1/2");
$f = Fraction(-2,5);
Note that $c will be 2/3, $d will be 14/3, $e will be -3/2, and $f will be -2/5.
Once you have created a fraction object, you can use it as you would any real number. For example:
Context("Fraction");
$a = Compute("1/2");
$b = Compute("1/3");
$c = $a - $b;
$d = asin($a);
$e = $b**2;
Here $c will be the equivalent of Compute("1/6"), $d will be equivalent to Compute("pi/6"), and $e will be the same as Compute("1/9");
You can an answer checker for a fraction in the same way as you do for ALL MathObjects -- via its cmp() method:
ANS(Compute("1/2")->cmp);
or
$b = Compute("1/2");
ANS($b->cmp);
There are several options to the cmp() method that control how the answer checker will work. The first is controls whether unreduced fractions are accepted as correct. Unreduced fractions are allowed in the Fraction and Fraction-NoDecimals contexts, but not in the LimitedFraction context. You can control this using the studentsMustReduceFractions option:
Context("Fraction");
ANS(Compute("1/2")->cmp(studentsMustReduceFractions=>1));
or
Context("LimitedFraction");
ANS(Compute("1/2")->cmp(studentsMustReduceFractions=>0));
The second controls whether warnings are issued when students don't reduce their answers, or to mark the answer incorrect silently. This is specified by the showFractionReductionWarnings option. The default is to report the warnings, but this option has an effect only when studentsMustReduceFractions is 1, and so only in the LimitedFraction context. For example,
Context("LimitedFraction");
ANS(Compute("1/2")->cmp(showFractionReductionWarnings=>0));
turns off these warnings.
The final option, requireFraction, specifies whether a fraction MUST be entered (e.g. one would have to enter 2/1 for a whole number). The default is 0.
In addition to these options for cmp(), there are Context flags that control how fractions are handled. These include the following.
reduceFractions
This determines whether fractions are reduced automatically when they are created. The default is to reduce fractions (except when studentsMustReduceFractions is set), so Compute("4/6") would produce the fraction 2/3. To leave fractions unreduced, set reduceFractions=>0. The LimitedFraction context has studentsMustReduceFractions set, so reduceFractions is unset automatically for students, but not for correct answers, so Fraction(2,4) would still produce 1/2, even though 2/4 would not be allowed in a student answer.
strictFractions
This determines whether division is allowed only between integers or not. If you want to prevent division from accepting non-integers, then set strictFractions=>1 (and also strictMinus=>1 and strictMultiplication=>1). These are all three 0 by default in the Fraction and Fraction-NoDecimals contexts, but 1 in LimitedFraction.
allowMixedNumbers
This determines whether a space between a whole number and a fraction is interpretted as implicit multiplication (as it usually would be in WeBWorK), or as addition, allowing "4 1/2" to mean "4 and 1/2". By default, it acts as multiplication in the Fraction and Fraction-NoDecimals contexts, and as addition in LimitedFraction. If you set allowMixedNumbers=>1 you should also set reduceConstants=>0. This parameter used to be named allowProperFractions, which is deprecated, but you can still use it for backward-compatibility.
showMixedNumbers
This controls whether fractions are displayed as proper fractions or not. When set, 5/2 will be displayed as 2 1/2 in the answer preview area, otherwise it will be displayed as 5/2. This flag is 0 by default in the Fraction and Fraction-NoDecimals contexts, and 1 in LimitedFraction. This parameter used to be named showProperFractions, which is deprecated, but you can still use it for backward-compatibility.
requireProperFractions
This determines whether fractions MUST be entered as proper fractions. It is 0 by default, meaning improper fractions are allowed. When set, you will not be able to enter 5/2 as a fraction, but must use "2 1/2". This flag is allowed only when strictFractions is in effect. Set it to 1 only when you also set allowMixedNumbers, or you will not be able to specify fractions bigger than one. It is off by default in all four contexts. You should not set both requireProperFractions and requirePureFractions to 1.
requirePureFractions
This determines whether fractions MUST be entered as pure fractions rather than mixed numbers. If allowMixedNumbers is also set, then mixed numbers will be properly interpretted, but will produce a warning message and be marked incorrect; that is, 2 3/4 would be recognized as 2+3/4 rather than 2*3/4, but would generate a message indicating that mixed numbers are not allowed. This flag is off by default in all four contexts. You should not set both requirePureFractions and requireProperFractions to 1.
Fraction objects have two methods that can be useful when reduceFractions is set to 0. The reduce() method will reduce a fraction to lowest terms, and the isReduced() method returns true when the fraction is reduced and false otherwise.
If you wish to convert a fraction to its numeric (real number) form, use the Real() constructor to coerce it to a real. E.g.,
$a = Compute("1/2");
$r = Real($a);
would set $r to the value 0.5. Similarly, use Fraction() to convert a real number to (an approximating) fraction. E.g.,
$r = Real(.5);
$a = Fraction($r);
would set $a to be 1/2. The fraction produced is good to about 6 decimal places, so it can't be used for numbers that are too small.
A side-effect of using the Fraction context is that fractions can be used to take powers of negative numbers when the reduced form of the fraction has an odd denominator. Thus (-8)^(1/3) will produce -2 as a result, while in the standard Numeric context it would produce an error.