1

I thought (defun string-integer-p (string) was cool, I found it in the emacswiki.

Is there a variant of it I can use to test if string contains float eg. "8.3"

  • Emacs Wiki: (defun string-float-p (string) (if (string-match "\`[-+]?[0-9]+\\.[0-9]*\\'" string) t nil)) -- emacswiki.org/emacs/ElispCookbook – lawlist Jul 8 '18 at 22:40
  • 1
    Please provide the code for string-integer-p in the question, or at least link to the wiki page that defines it. – Drew Jul 9 '18 at 0:48
  • @lawlist: Please consider posting that as an answer. – Drew Jul 9 '18 at 0:48
  • @lawlist That solution neglects all the problems that result from exponent representation. – Tobias Jul 9 '18 at 15:15
2

I think string-to-number is usable here. It has the unfortunate property that it returns 0 for non-numeric strings (an option to return nil would seem sensible, especially as that's what its helper actually does); however 0 is not a float, so...

(defun my-string-float-p (str)
  "Non-nil if string STR represents a floating point number."
  (floatp (string-to-number str)))

(my-string-float-p "x")
nil

(my-string-float-p "0")
nil

(my-string-float-p "0.0")
t
  • 3
    my-string-float-p gives t for (my-string-float-p "0.1Hello"). Is that intended behavior? – Tobias Jul 9 '18 at 7:51
  • 2
    Right, (string-to-number "0.1Hello") returns 0.1. It's documented (trailing chars are ignored), so it's "intended" in that respect. Whether it's useful behaviour rather depends on your use-case. Thanks for pointing it out. – phils Jul 9 '18 at 10:20
  • for my use case its ok – american-ninja-warrior Jul 9 '18 at 12:26
3

Since one can edit program texts in many programming languages with emacs it is important to note that the floating point syntax can vary with the programming language. For an instance 1.2d3 is a floating point number in Fortran but not in Elisp.

In the following I present a function my-string-float-p that returns t if the whole string is read as a floating point number by the Elisp reader.

One can interpret the first object in the string as lisp by read and test this object with floatp.

If read has gobbled all characters from the string that is the only thing represented by the string.

(defun my-string-float-p (str)
  "Non-nil if string STR represents a floating point number."
  (with-temp-buffer
    (insert str)
    (goto-char (point-min))
    (condition-case nil
        (and (floatp (read (current-buffer)))
             (eobp))
        (error nil))))

Test suite:

(my-string-float-p "x")
nil
(my-string-float-p "0")
nil
(my-string-float-p "0.0")
t
(my-string-float-p "8.3")
t
(my-string-float-p "0.1Hello")
nil
(my-string-float-p "0.1 Hello")
nil
(my-string-float-p "(")
nil
(my-string-float-p ")")
nil
  • 1
    (defun f (s) (floatp (read s))) does the same thing for a string arg, no? At least for your test suite it seems to. – Drew Jul 9 '18 at 14:55
  • @Drew I added a test case (my-string-float-p "0.1 Hello") which does not return the expected nil with (f "0.1 Hello") and your (defun f (s) (floatp (read s))). – Tobias Jul 9 '18 at 15:00
1
(defun string-float-p (str)
  "Non-nil if string STR represents a floating point number."
  (let ((rd  (read-from-string str)))
    (and (floatp (car rd))  (eq (cdr rd) (length str)))))
  • Protection against reading strings with erroneous lisp is also necessary (condition-case nil ... (error nil)). – Tobias Jul 9 '18 at 18:59
  • A similar effect would be possible with (let ((rd (read (concat "(" str ")")))) (and (floatp (car rd)) (null (cdr rd)))). That version would ignore spaces at front and tail of str. – Tobias Jul 9 '18 at 19:02

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.