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.
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?
On Sat, Jan 3, 2009 at 7:06 PM, Mark H. <mark.hoem...@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).
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.
On Jan 3, 10:06 pm, "Mark H." <mark.hoem...@gmail.com> wrote:
> 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?
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:
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