Clojure 1.1.0
user=> (* 100M 1.1)
110.00000000000001
user=> (class (* 100M 1.1))
java.lang.Double
Such thing are really hard to find and this can be easily produced by
non-technical person, if he is using some kind of DSL which is based
on Clojure. Shoudn't it be BigDecimal instead?
Wbr,
Jevgeni
IMO: No it should not.
(Maybe someone else can explain this more succinctly, I feel like I'm
muddling the point I'm trying to make.)
The whole point of using BigDecimal is to avoid the non-intuitive
funkyness that will result from using binary floating point (Double,
Float) while expecting decimal behavior. Furthermore, BigDecimal can
be arbitrarily precise, while Double has limited precision. Returning
a BigDecimal from a (* 100M 1.1) would be pretending that the
calculation is more precise than it actually is.
Your example is well chosen for my line of argument. Are you aware
that 0.1 can't be represented exactly as a Double? (It has a
non-terminating representation in binary, just as 1/3 =
0.33333333333333... does in decimal.) 0.1M, however can be represented
exactly as a BigDecimal. People can be awfully picky about predictable
arithmetic behavior when it comes to Money, which is what BigDecimal
is often used for.
(From a DSL standpoint, it might have been better if Clojure had
chosen 1.1 as the syntax for BigDecimal and 1.1D (or similar) for
Double, but there's no fixing that now.)
// Ben
Hope this helps,
Lauri
> --
> You received this message because you are subscribed to the Google
> Groups "Clojure" group.
> To post to this group, send email to clo...@googlegroups.com
> Note that posts from new members are moderated - please be patient with your first post.
> To unsubscribe from this group, send email to
> clojure+u...@googlegroups.com
> For more options, visit this group at
> http://groups.google.com/group/clojure?hl=en
>
If is this is never to be fixed by some reason (which one can it be?),
then let me ask another question. I wonder, if there is a requirement
for user to write custom business rules himself (lets say he wants to
increase the price on 10%) and he uses 1.1, can I solve this issue
with Clojure core without using external parsers/preprocessors?
Something like replacing the 1.1 with 1.1M or 11/10 before evaluating
the code?
Wbr,
Jevgeni
On Jan 17, 7:47 pm, B Smith-Mannschott <bsmith.o...@gmail.com> wrote:
> On Sat, Jan 16, 2010 at 23:13, Jevgeni Holodkov
>
> decimal. Entered 0.1 is actually a very precise number and the fact
> that it gets imprecise somewhere internally should now affect, IMHO,
> the result of multiplying two very precise numbers. What's the point
There is no such thing as a "precise" or "imprecise" number as far as
the computer is concerned. What differs is the interpretation that
humans (programmers and users) make of the data items. The rules of
floating-point arithmetic (in Clojure and pretty much anywhere else)
are designed with the expectation that floats will be interpreted as
approximations. So as soon as you use a single float in some
expression, the whole expression becomes something to be considered
approximate, and therefore it will be of float type.
Unlike most languages, Clojure has a way to express precise non-
integer numbers: ratios. Just use 11/10 instead of 1.1 (or (+ 1 1/10)
if you prefer), and you won't see any floating-point result. In fact,
what you are complaining about is simply that the input string 1.1 is
interpreted as a float rather than as a ratio. Obviously it can't mean
both, so some choice has to be made.
> If is this is never to be fixed by some reason (which one can it be?),
> then let me ask another question. I wonder, if there is a requirement
> for user to write custom business rules himself (lets say he wants to
> increase the price on 10%) and he uses 1.1, can I solve this issue
> with Clojure core without using external parsers/preprocessors?
> Something like replacing the 1.1 with 1.1M or 11/10 before evaluating
> the code?
I don't think so. The very first step of Clojure's expression
processing system, the reader, already interprets 1.1 as a floating-
point constant. You would need your own reader to give a different
meaning to the input string 1.1. However, the good news is that you
would only need a different reader, you could then plug its results
into the standard evaluation system.
Konrad.
Or, if you're taking a string from the user as your very first step,
you could (*choke*) apply regular expressions to append "M" to every
piece of floating-point syntax.
However, if those floating-point numbers come from some piece of
software other than a keyboard driver -- for example, they're read as
the value of a slider control -- then be careful of falsely assigning
decimal status to a string representation of a float...
Hacking Clojure's reader to replace the floating-point reader
shouldn't be too hard. Indeed, this might be something that can be
parameterized a la Common Lisp's radix/base settings.