Math functions

142 views
Skip to first unread message

Mark Engelberg

unread,
Jan 3, 2009, 2:48:08 PM1/3/09
to clo...@googlegroups.com
I've noticed that Clojure is missing several math functions that come
standard with most programming languages, especially other
Schemes/Lisps. Many of these functions are available in java's math
library, but only for doubles.

I am attaching a file that tries to "do the right thing" for Clojure's
other numeric types, for inclusion in the contribs, or possibly the
core. I have sent in a contributor agreement, but am unfamiliar with
the submission process. Do I just attach the file here, or is there
somewhere I'm supposed to upload them? Are there standards for
documenting and including test cases that I need to follow?

I started with expt, because the lack of expt was the biggest nuisance
for me. If you give it an exact number (i.e., not a floating point),
and an integer exponent, it will give you a precise result, otherwise
it calls Java's double version of pow. I posted this the other day,
but it is included again here, with a couple minor tweaks.

Next, I did floor, ceiling, and round. All of these functions yield
an integer if the input is an exact number, otherwise they do whatever
Java's double version does (Java's floor and ceiling yield doubles,
and round yields an integer or the max int if out of range). round is
a round-up to mimic Java's behavior (I think that in Scheme, round is
usually a round-to-even, so this is a potential gotcha to be aware
of).

Those are the additions that I consider most essential.

While I was at it, I added implementations for abs and mod, which are
standard in most languages, and gcd which is standard in Scheme.

Also, I added a version of sqrt that gives an exact answer whenever
there is an exact answer (works on integers, decimals, and fractions),
otherwise it gives you whatever Java's sqrt produces. I don't know
how generally useful this is, but it's the behavior I've come to
expect from working with Scheme.

I hope everyone finds these functions as useful as I do.

P.S. While writing these functions, I really liked working with
Clojure's multimethod system, and found it very intuitive to set up
functions that do the right things. For example, expressing a custom
version of expt when the base is "exact" and the power is "some kind
of integer type" was a snap.

math.clj

Mark H.

unread,
Jan 3, 2009, 10:06:06 PM1/3/09
to Clojure
On Jan 3, 11:48 am, "Mark Engelberg" <mark.engelb...@gmail.com> wrote:
> If you give it an exact number (i.e., not a floating point),

Floating-point numbers are exact -- it's their operations that may not
be. *ducks*

Seriously, handy code -- many thanks! I should check with someone
whether sqrt(a/b) -> sqrt(a)/sqrt(b) is a fair assumption. Would you
find a sqrt that returns complex numbers for negative inputs (it would
be the appropriate branch of the sqrt function in order to make it
single-valued) useful?

mfh

Mark Engelberg

unread,
Jan 4, 2009, 12:02:24 AM1/4/09
to clo...@googlegroups.com
On Sat, Jan 3, 2009 at 7:06 PM, Mark H. <mark.h...@gmail.com> wrote:
> Would you
> find a sqrt that returns complex numbers for negative inputs (it would
> be the appropriate branch of the sqrt function in order to make it
> single-valued) useful?

Ideally I'd also like that, but since complex numbers aren't part of
Clojure's numeric tower, and since there isn't one official Java
implementation of complex numbers (as far as I know), I just do what
Java's sqrt function does (i.e., return NaN).

vogelrn

unread,
Jan 3, 2009, 10:46:23 PM1/3/09
to Clojure
sqrt(a/b) should always be equal to sqrt(a)/sqrt(b) since (a/b)^m =
a^m/b^m for b != 0. However, I'm unsure of whether it's the best
option for ratios because unless both the numerator and the
denominator are perfect squares, you're going to end up with a float
anyway. This is trading an extra sqrt for precision in the relatively
uncommon situation where both numbers are perfect squares.

As for taking square roots involving complex numbers, I've been
considering that as well, but I think it might be a bad idea to have
it as a part of the normal sqrt function. In the majority of
situations, taking the square root of a negative number is a bad thing
and probably shouldn't be allowed. An alternative sqrt associated
with complex numbers could be appropriate instead.

Mark H.

unread,
Jan 5, 2009, 9:27:51 AM1/5/09
to Clojure
On Jan 3, 7:46 pm, vogelrn <voge...@gmail.com> wrote:
> sqrt(a/b) should always be equal to sqrt(a)/sqrt(b) since (a/b)^m =
> a^m/b^m for b != 0.  However, I'm unsure of whether it's the best
> option for ratios because unless both the numerator and the
> denominator are perfect squares, you're going to end up with a float
> anyway.  This is trading an extra sqrt for precision in the relatively
> uncommon situation where both numbers are perfect squares.

*nodsnodsnods*

> As for taking square roots involving complex numbers, I've been
> considering that as well, but I think it might be a bad idea to have
> it as a part of the normal sqrt function.  In the majority of
> situations, taking the square root of a negative number is a bad thing
> and probably shouldn't be allowed.  An alternative sqrt associated
> with complex numbers could be appropriate instead.

I agree. Perhaps this article will be relevant for those interested
in such a project:

http://www.eecs.berkeley.edu/Pubs/TechRpts/1992/6127.html

mfh

Stuart Sierra

unread,
Jan 5, 2009, 7:28:38 PM1/5/09
to Clojure
On Jan 3, 2:48 pm, "Mark Engelberg" <mark.engelb...@gmail.com> wrote:
> I've noticed that Clojure is missing several math functions that come
> standard with most programming languages, especially other
> Schemes/Lisps.  Many of these functions are available in java's math
> library, but only for doubles.

Nice work, Mark. Are you on clojure-contrib? This would be a useful
addition.
-Stuart Sierra
Reply all
Reply to author
Forward
0 new messages