WeBWorK Main Forum

mod (%) irregularities ?

mod (%) irregularities ?

by Zak Zarychta -
Number of replies: 4
I'm trying to implement a simple reduction of a fraction with the following 

$numer = (($a*$d + $b*$c)*$f - ($b*$d*$e));
$denom = ($b*$d*$f);
my $count;
for ($count=2; $count<10; $count++) {
if (($numer % $count == 0) && ($numer % $count == 0)) {
$numer = $a/$count;
$denom = $b/$count;
$count = $count-1;

When in a conventional perl script  for $numer = 75 and $denom = 21 the previous routine sets $numer = 25 and $denom =7.

In my WeBWorK question 1 and 0.3333 are returned respectively for $numer and $denom. Why might this be so? Is this something to do with the mod symbol?

In reply to Zak Zarychta

Re: mod (%) irregularities ?

by D. Brian Walton -

You have the wrong condition typed in the divisibility test (2nd should be $denom % $count)

Your update of $numer and $denom should be:

$numer = $numer/$count;
$denom = $denom/$count;

Also, instead of decreasing count by 1, just change the if statement to a while statement.

Finally, if you are only going to check a small group of possible divisors, you might think about changing $count to $prime and then use a short list of known primes.

Try the following:
my $prime;
foreach $prime (2, 3, 5, 7, 11, 13, 17, 19) { 
    while (($numer % $prime == 0) && ($denom % $prime == 0)) {
        $numer = $numer / $prime; 
        $denom = $denom / $prime;

D. Brian Walton
In reply to D. Brian Walton

Re: mod (%) irregularities ?

by Danny Glin -
If you are looking to reduce fractions, there are some existing functions in PGauxiliaryFunctions.pl.  In particular, a gcd function, and (as I just discovered) the reduce function.

I use gcd to do this, so my code looks like:

$g = gcd($numer,$denom);
$numer = $numer/$g;
$denom = $denom/$g;

Having just read the code for reduce, you should be able to simply do:
($numer,$denom) = reduce($numer,$denom);

One thing to note is that if you pass a negative fraction to reduce, it will return a negative numerator and a positive denominator.  I've never actually used this before, but looking at the code it should work as expected.

In reply to D. Brian Walton

Re: mod (%) irregularities ?

by Paul Pearson -

Are you trying to randomly generate a reduced fraction? Why not do something like

do {
$num = random(2,9,1);
$den = random(2,9,1);
} until (
gcd($num,$den) == 1

Note that $num and $den above could be defined in terms of other scalars $a, $b, etc. all inside of the executable portion of do { execute }. I don't know how gcd( , ) handles negative integer inputs, but you can easily test that yourself.

If you need something more advanced, take a look at the xgcd method in the MatrixUnimodular.pl macro file located in OpenProblemLibrary/macros/FortLewis (or NationalProblemLibrary/macros/FortLewis).


Best Regards,

Paul Pearson
In reply to Zak Zarychta

Re: mod (%) irregularities ?

by Alex Jordan -
If you load contextFraction.pl, then there is a Fraction Context with a Math Object Fraction that automatically reduces fractions (this is a flag that can be toggled.)

$fraction = Fraction($numer,$denom);

I find it useful to then return to the Numeric Context

$fraction = Compute("$fraction");

Or students might get error messages implying they should be entering a fraction, even when $fraction is actually a whole number.

Read more about the flags for Context("Fraction") here.

If you have a Fraction Math Object and wish to extract the reduced numerator or denominator, first create an array from $f:

@g = $f->value;

And then $g[0] is the numerator and $g[1] is the denominator. These are perl integers, not Math Objects, so you might want to set something like

$num = Compute($g[0]);

$den= Compute($g[1]);