crenz has asked for the wisdom of the Perl Monks concerning the following question:
Even after programming Perl for quite a few years, you can still be bitten by unexpected behaviour exhibited by Perl's builtin operators. Today, I was trying to calculate the modulo of several values. The catch: The modulus is not an integer, but a fraction! I expected this to just work but apparently, it does not:
$ perl e 'print 4 % 0.5, "\n";'
Illegal modulus zero at e line 1.
$ perl e 'print 4 % 2.5, "\n";'
0
I would have expected these snippets to print 0 and 1.5, respectively.
In my application, I can circumvent this easily, but I'm just wondering: How come Perl isn't just doing “the right thing” here? Just to check my own sanity, I tried the same calculations using octave (using the rem function), which deals with fractions no problem. MS' documentation for JScript also lists an example using fractions. Given that this behaviour is not documented, I'd consider it a bug in the 5.8.1 version that I use.
Update: Thanks, I overlooked the part where it says “integer operands”… I still think it's a default functionality that should be implemented, though. If I want C compatibility, I'll use C ;).
Re: Modulo of fraction?
by Ido (Hermit) on Jun 27, 2005 at 13:55 UTC

It's documented that % is only for integers:
From perlop:
Binary "%" computes the modulus of two numbers. Given integer operands $a and $b : ...
 [reply] 
Re: Modulo of fraction?
by Limbic~Region (Chancellor) on Jun 27, 2005 at 13:56 UTC

crenz,
"Given that this behaviour is not documented..."
Oh but it is. From perlop
Binary "%" computes the modulus of two numbers. Given integer operands $a and $b :
 [reply] 

 [reply] 

Ido,
Actually  it could be anywhere from 1 to 119 seconds but I think it was closer to about 10.
 [reply] 
Re: Modulo of fraction?
by herveus (Parson) on Jun 27, 2005 at 13:58 UTC

Howdy!
perldoc perlop says:
Binary "%" computes the modulus of two numbers. Given
integer operands "$a" and "$b": If "$b" is positive, then
"$a % $b" is "$a" minus the largest multiple of "$b" that is
not greater than "$a". If "$b" is negative, then "$a % $b"
is "$a" minus the smallest multiple of "$b" that is not less
than "$a" (i.e. the result will be less than or equal to
zero). Note than when "use integer" is in scope, "%" gives
you direct access to the modulus operator as implemented by
your C compiler. This operator is not as well defined for
negative operands, but it will execute faster.
Note the part about "integer operands". I suspect that the arguments got truncated to integers, leading to the cases "4 % 0" and "4 % 2". One can readily imply that Perl does not define % for noninteger arguments. If you need that, you need to write your own implementation.
 [reply] 
Re: Modulo of fraction?
by chipmonkey (Initiate) on Jun 27, 2005 at 16:33 UTC

# get the fractional portion of a number
sub frac { $_[0]int($_[0]) }
# find the remainder in a real division
sub rem { $_[1]*frac($_[0]/$_[1]) }
 [reply] [d/l] 
Re: Modulo of fraction?
by Old_Gray_Bear (Bishop) on Jun 27, 2005 at 16:37 UTC

I believe that modulo arithmetic is only defined for intergers. See the Wolfram MathWorld discussion of 'Congruence'(http://mathworld.wolfram.com/Congruence.html). Note: 'fractional congruence' is discussed in the final paragraphs of the article, as the solutions of a 'linear congruence equation'.

I Go Back to Sleep, Now.
OGB
 [reply] 

This becomes a battle of semantics. Mostly one only sees modulo arithmetic defined for integers, where the modulus needs to be a positive integer. But there are definely analogous systems that deal with fractions, and i suppose that they can be extended to reals, although taking the modulus of something (mod pi) seems pretty weird to me.
But as a mathematician, as long as the system definition is consistent, there shouldnt be any problem.
I do recall in an old (1950's) number theory book that got from a clearance rack (old crap free for the taking) from my universities math department (which i still posess), it is left as an exercise to extend modular arithmetic to include fractions. Ouch!, but such things are feasible.
I should read the link you cited, but am way too busy right now.
 [reply] 

... although taking the modulus of something (mod pi) seems pretty weird ... Not only weird but for such transcendental numbers as pi or e I can imagine that the result is undefined!
CountZero "If you have four groups working on a compiler, you'll get a 4pass compiler."  Conway's Law
 [reply] 

Re: Modulo of fraction?
by fglock (Vicar) on Jun 27, 2005 at 19:24 UTC

sub my_mod {
my ( $a, $b ) = @_;
my $div = $a / $b;
return $a  int( $div ) * $b;
}
print my_mod( 4, 1.5 ), "\n"; # 1
print my_mod( 4, 0.5 ), "\n"; # 0
print my_mod( 4, 0.7 ), "\n"; # 0.5
 [reply] [d/l] 
Re: Modulo of fraction?
by ambrus (Abbot) on Jun 27, 2005 at 14:08 UTC

 [reply] 

 [reply] 

I think/hope he's being ironic :).
 [reply] 

Re: Modulo of fraction?
by TedPride (Priest) on Jun 27, 2005 at 18:28 UTC

If it doesn't work, make yourself a sub to solve the problem instead of worrying about the why :)
use strict;
use warnings;
print myrem(4, 2.5);
sub myrem { return $_[0]  int ($_[0] / $_[1]) * $_[1]; };
You might also want to look at the overload / override modules on CPAN.  [reply] [d/l] 
Re: Modulo of fraction?
by Anonymous Monk on Nov 24, 2009 at 17:01 UTC

Quick solution, just multiply fraction by powers of two until it becomes integer. (you're dealing with binary numbers after all) Finally, divide integer remainder by same power of two
ex)
2 x (4 % 0.5) = 8 % 1 = 0
2 x (4 % 2.5) = 8 % 5 = 3
4 % 2.5 = 3/2
Also, the trick to extending mod to fractions is Bezout's identity.
 [reply] 

