Page 1 of 1

newbie question: floating point addition operation

Posted: Tue Mar 05, 2013 12:35 am
by hajovonta
Can someone explain this:

Code: Select all

CG-USER(9): (+ 2.32 0.001)
2.3209999
I have Allegro Common Lisp, 9.0, Windows 7 machine.

What is the proper way to correctly display 2.321 ?

Re: newbie question: floating point addition operation

Posted: Tue Mar 05, 2013 2:30 am
by Konfusius
Since floating point numbers are represented internally as numbers by the base of two there isn't a way to represent 0.001 exactly. There will always be rounding errors. This isn't a problem of Lisp but of floating point arithmetic in general. The only way around it is to print it rounded:

Code: Select all

(format t "~,5f" (+ 2.32 0.001))
-> 2.32100

Re: newbie question: floating point addition operation

Posted: Tue Mar 05, 2013 3:35 am
by hajovonta
Thanks, that suits for me.

Re: newbie question: floating point addition operation

Posted: Wed Mar 06, 2013 7:14 am
by marcoxa

Re: newbie question: floating point addition operation

Posted: Wed Mar 06, 2013 11:58 am
by hajovonta
Maybe it was my high expectations :)

Re: newbie question: floating point addition operation

Posted: Thu Mar 07, 2013 10:22 am
by Kompottkin
hajovonta wrote:Maybe it was my high expectations :)
If you want exact rationals, use exact rationals. :)

Code: Select all

CL-USER> (+ 232/100 1/1000)
2321/1000

Re: newbie question: floating point addition operation

Posted: Thu Mar 07, 2013 2:13 pm
by hajovonta
ok, but then I want to display the result in floating point format...

Re: newbie question: floating point addition operation

Posted: Fri Mar 08, 2013 4:56 am
by Konfusius
You can convert rationals to floats:

Code: Select all

(float (+ 232/100 1/1000))
-> 2.321

Re: newbie question: floating point addition operation

Posted: Sat Mar 09, 2013 3:42 am
by Kompottkin
Konfusius wrote:You can convert rationals to floats:

Code: Select all

(float (+ 232/100 1/1000))
-> 2.321
Technically, that (somewhat) reintroduces the problem...

Code: Select all

L> (format t "~E" (float (+ 232/100 1/1000)))
2.3210001e+0
NIL
L> (= 2.3210001 (float (+ 232/100 1/1000)))
T
The Right Thing[TM] would be to use something like Wu-Decimal:

Code: Select all

L> (ql:quickload "wu-decimal")
; Loading "wu-decimal"
[package wu-decimal]...
("wu-decimal")
L> (wu-decimal:enable-decimal-printing-for-ratios)
NIL
L> (format t "~A" (+ 232/100 1/1000))
2.321
NIL
Of course, I'm nitpicking. If you're just hacking something together to quickly visualize something, using floating point and rounding the results isn't so bad.