user=> (map #(mod % 3) (range -9 9))
(3 1 2 3 1 2 3 1 2 0 1 2 0 1 2 0 1 2)
It disagrees with, for example, Ruby:
irb(main):002:0> (-9..9).map{|x| x % 3}
=> [0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0]
And python:
>>> map( lambda x: x % 3, range(-9,9) )
[0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2, 0, 1, 2]
--Chouser
> I spoke too soon. Apparently from the Lisp HyperSpec
> mod performs the operation floor on number and divisor and returns the
> remainder of the floor operation.
> Which would indicate that mod1 is not consistent with LISP.
> Seeing Java doesn't have a proper mod, it would seem sensible to
> follow the LISP/Ruby/Python convention...
I agree.
Absent some compelling reason to the contrary, I think it would be a
wise policy for Clojure to defer to Common Lisp in cases like this.
Those behaviors have been pored over for years by really smart people--
not a guarantee of correctness, of course, but the probability is
really high.
The fact that apparently we can also simultaneously include the really
smart folks who've been refining Python and Ruby for years is a great
bonus.
--Steve
Thanks for doing all the hard work. :-)
How about:
(defn mod42
"Modulus of num and div. Truncates toward negative infinity."
[num div]
(if-not (and (integer? num) (integer? div))
(throw (IllegalArgumentException. "mod requires two integers"))
(let [m (rem num div)]
(if (or (zero? m) (> (* num div) 0))
m
(+ m div)))))
--Chouser
But simpler and clearer. Thanks for the catch.
--Chouser
Thanks for noticing and fixing the problem.
Although Chouser's version is slightly more compact than Pratley's, I
wonder if a multiplication followed by a single comparison to zero is
a significantly more or less expensive operation than several
comparisons to zero? My instinct is that multiplication is more
expensive, but I haven't had a chance to really check.
Just for giggles, here's how SBCL (Steel Bank Common Lisp) defines
the two functions:
(defun rem (number divisor)
#!+sb-doc
"Return second result of TRUNCATE."
(multiple-value-bind (tru rem) (truncate number divisor)
(declare (ignore tru))
rem))
(defun mod (number divisor)
#!+sb-doc
"Return second result of FLOOR."
(let ((rem (rem number divisor)))
(if (and (not (zerop rem))
(if (minusp divisor)
(plusp number)
(minusp number)))
(+ rem divisor)
rem)))
Notice that despite the documentation, MOD does not actually call
FLOOR. It indirectly calls TRUNCATE via REM. It's also important to
notice that Common Lisp is a Lisp-2, so that we can store the result
of the REM call in a variable with the same name in the LET form.
Aloha,
David Sletten
The real hit would come with bignums, no? But as far as the routine
use of MOD goes we're probably talking about fixnums > 99% of the time.
Aloha,
David Sletten