Subject: Re: String to real
From: Erik Naggum <erik@naggum.no>
Date: 2000/06/08
Newsgroups: comp.lang.lisp
Message-ID: <3169487578816052@naggum.no>

* Tim Bradshaw <tfb@cley.com>
| This comes up quite regularly.  There really isn't a good answer --
| there is PARSE-INTEGER but not PARSE-FLOAT.  People will tell you to
| use READ-FROM-STRING, but this is generally bad advice because you
| have no idea what's in the string, and so you could get back
| anything, or perform arbitrarily complex computations unless you
| turn off *READ-EVAL*.  So be careful if you do this.

  This is fairly strange advice.  Let's decide to _write_ parse-float,
  instead of this repeated lamentation.  Somewhere in every Common
  Lisp implementation, there's a function that takes a strings of
  characters and returns a floating point number.  It may be hard to
  call, it may require other internals to be set up properly, or it
  may be embedded in something else that makes it hard to access right
  away, but it's there.

  Language design is all about deciding on interfaces to well-defined
  functionality, _not_ about implementing them nicely.  In fact, we're
  allowed to be as implementation-dependent as we could possibly get
  if we adhere to the principle of exporting and advertising a clean
  interface.  Before you object, consider that it is a lot cleaner
  than asking people to go off and do all the implementation-dependent
  stuff in their _own_ code, because that's just plain gross.

  For instance, in Allegro CL, there's a nice little function called
  make-float that returns a floating point number if given a
  read-buffer with characters satisfying the pattern matching a
  floating point number in it, but a read-buffer is an _entrenched_
  data type, and accessing it is non-trivial without sources, so only
  supported customers who have signed the limited source license can
  use it.  I'm not super-thrilled about this, but here's how to use
  it, given an input string with its usual start and end positions:

#+franz-inc
(defun parse-float (string &key (start 0) end)
  (let* ((length (- (or end (length string)) start)))
    (excl::make-float (vector (subseq string start end) length 0 length))))

  This function will parse a floating point number and return it just
  as the reader would (like obeying *read-default-float-format*), but
  will return 0.0 if there is no discernible floating point number in
  the string you gave it.  Caveat emptor or something.

  An improvement on this function is to take a string and figure out
  where the floating point number ends and return that position, too.

  _Or_ you could just write some FFI wrappping around the math library
  functions of your favorite operating system's "native" compiler, but
  that's completely immaterial to me: All I want is a function called
  "parse-float" which takes a string containing the usual read syntax
  for floating point numbers and gives me the floating point number
  that would print back as that string, if at all possible, or the
  nearest floating point model number¹ if not.

#:Erik
-------
¹ That's what they call it in Ada, anyway.
-- 
  If this is not what you expected, please alter your expectations.