Beefy Boxes and Bandwidth Generously Provided by pair Networks
Perl: the Markov chain saw
 
PerlMonks  

Modulo of fraction?

by crenz (Priest)
on Jun 27, 2005 at 13:43 UTC ( #470263=perlquestion: print w/ replies, xml ) Need Help??
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 built-in 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 ;-).

Comment on Modulo of fraction?
Download Code
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 : ...
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 :

    Cheers - L~R

      One minute!;)
        Ido,
        Actually - it could be anywhere from 1 to 119 seconds but I think it was closer to about 10.

        Cheers - L~R

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 non-integer arguments. If you need that, you need to write your own implementation.

    yours,
    Michael
Re: Modulo of fraction?
by ambrus (Abbot) on Jun 27, 2005 at 14:08 UTC

    This is for C (and BASIC) compatibility.

      Are you saying it was it was designed to be compatible with C and BASIC, or are you simply pointing out that the design is compatible with C and BASIC? (and Turbo Pascal and MODULA-II and Java).

        I think/hope he's being ironic :-).
Re: Modulo of fraction?
by chipmonkey (Initiate) on Jun 27, 2005 at 16:33 UTC
    For archival purposes,
    # 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]) }
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

      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.

        ... 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 4-pass compiler." - Conway's Law

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.
Re: Modulo of fraction?
by fglock (Vicar) on Jun 27, 2005 at 19:24 UTC

    You can rewrite the modulus function as:

    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
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.

Log In?
Username:
Password:

What's my password?
Create A New User
Node Status?
node history
Node Type: perlquestion [id://470263]
Approved by Arunbear
Front-paged by Tanalis
help
Chatterbox?
and the web crawler heard nothing...

How do I use this? | Other CB clients
Other Users?
Others about the Monastery: (12)
As of 2014-12-26 20:10 GMT
Sections?
Information?
Find Nodes?
Leftovers?
    Voting Booth?

    Is guessing a good strategy for surviving in the IT business?





    Results (175 votes), past polls