Parsing large real numbers

Discussion of Common Lisp

Parsing large real numbers

Postby vityok » Tue Jul 22, 2008 11:45 pm

Hello,

What is the proper way to read (parse) real numbers in Common Lisp?

The problem is, that I have to read relatively large real numbers, and both SBCL and CLISP fail:
Code: Select all
[4]> (- (read-from-string "1169991858.90605") 1169991859.32605)
0.0
[5]> (- (read-from-string "1169991858.90605") (read-from-string "1169991859.32605"))
0.0

On SBCL, I have PARSE-NUMBER package installed, but it also fails in a similar way:
Code: Select all
* (- (parse-number:parse-number "1169991858.90605") 1169991859.90605)
0.0
* (parse-number:parse-number "1169991858.90605")
1.1699918e9

The numbers are actually a number of seconds from the Unix Epoch.

Thank you
vityok
 
Posts: 20
Joined: Fri Jul 11, 2008 6:20 am
Location: Kyiv, Ukraine

Re: Parsing large real numbers

Postby death » Wed Jul 23, 2008 1:31 am

In this particular case, maybe it would be sufficient to use double-floats:

Code: Select all
(- (let ((*read-default-float-format* 'double-float))
     (read-from-string "1169991858.90605"))
   1169991859.32605d0)
=> -0.4200000762939453d0
death
 
Posts: 17
Joined: Sat Jun 28, 2008 1:44 am

Re: Parsing large real numbers

Postby makia » Wed Jul 23, 2008 1:36 am

well, it's tricky field ...
you are using single-floats .... you can use double-floats so you will get:

CL-USER> (- (read-from-string "1169991858.90605") 1169991859.32605)
0.0
CL-USER> *read-default-float-format*
SINGLE-FLOAT
CL-USER> (setf *read-default-float-format* 'double-float)
DOUBLE-FLOAT
CL-USER> (- (read-from-string "1169991858.90605") 1169991859.32605)
-0.4200000762939453

it's part of the IEEE standard because you cant have exact representation in binary
I dont know of any real numbers common lisp library so you can choose precision ....
makia
 
Posts: 25
Joined: Tue Jul 22, 2008 2:37 am

Re: Parsing large real numbers

Postby Ramarren » Wed Jul 23, 2008 3:07 am

vityok wrote:The numbers are actually a number of seconds from the Unix Epoch.


CLISP also has arbitrary precision floats. Or course, those are slow. But in this particular case, if you may want to parse the seconds and second fraction as integers and either convert them to rational, or handle them separately. This might be overkill though if doubles suffice...

Code: Select all
(defun parse-decimal (string)
  (let ((dot (position #\. string)))
    (+ (parse-integer string :end dot)
       (/ (parse-integer string :start (1+ dot))
          (expt 10 (- (length string) (1+ dot)))))))

(- (parse-decimal "1169991858.90605") (parse-decimal "1169991859.32605")) => -21/50


This will parse a decimal number into a rational. This does not do any error checking or anything, so will fail on malformed input, but I hope you get the idea.
Ramarren
 
Posts: 613
Joined: Sun Jun 29, 2008 4:02 am
Location: Warsaw, Poland

Re: Parsing large real numbers

Postby vityok » Wed Jul 23, 2008 4:28 am

Thank you all for your help.

The approach with modifying default float format does work for me.

Thanks
vityok
 
Posts: 20
Joined: Fri Jul 11, 2008 6:20 am
Location: Kyiv, Ukraine


Return to Common Lisp

Who is online

Users browsing this forum: No registered users and 6 guests

cron