# elisp replace float number with half value

I need to replace below string:

``````(24.0000,28.0000) .. controls (27.3100,28.0000) and (29.9800,25.3100) .. (29.9800,22.0000)
``````

to:

``````(12,14) .. controls (13.655,14) and (14.99,12.655) .. (14.99,11)
``````

The rule is:

1. coordinate x and y divided by 2.
2. remove trailing zeros.
3. other parts keep it as is.

I wish to do it in elisp:

``````#+BEGIN_SRC elisp :results output
(let (str x y (i 0))
(setq str "
(24.0000,28.0000) .. controls (27.3100,28.0000) and (29.9800,25.3100) .. (29.9800,22.0000)
")
(while (string-match "(\\([0-9.]+\\),\\([0-9.]+\\))"  str i)
(setq i (match-end 0))
(setq x (/ (string-to-number (match-string 1 str) 10) 2))
(setq y (/ (string-to-number (match-string 2 str) 10) 2))
(print (format "%f,%f" x  y))
))
#+END_SRC

#+RESULTS:
:
: "12.000000,14.000000"
:
: "13.655000,14.000000"
:
: "14.990000,12.655000"
:
: "14.990000,11.000000"
``````

It can extract the numbers and do match on it, but how can I replace it within original string?

I am thinking about `replace-regexp-in-string` but it not good to do match on it.

• Well... the problem is, floating point numbers are internally stored in base-two representation, so, when they are printed in base-ten representation, some "strange" things may happen, just like in this comic: knowyourmeme.com/photos/1070750-i-m-not-a-robot . As for the technicalities of `replace-regexp-in-string` - what was the problem? Your regex should match what you need, although it will match more than you need. Also note that the third argument to this function could be a function which performs arbitrary calculations to produce substituted string. – wvxvw Nov 16 '17 at 8:51
• "trailing zero still not removed" - maybe try `%.3g` instead of `%.3f`? – npostavs Nov 16 '17 at 23:40
• @npostavs Exactly, %.3g works. Thanks – lucky1928 Nov 17 '17 at 1:21

After read wvxvw and npostavs's comments, it's good to do it below:

``````#+BEGIN_SRC elisp :results value
(defun my/rep(str)
(let ((val "") x y)
(when (string-match "\\([0-9.]+\\),\\([0-9.]+\\)" str)
(setq x (/ (string-to-number (match-string 1 str) 10) 2))
(setq y (/ (string-to-number (match-string 2 str) 10) 2))
(setq val (format "%.3g,%.3g" x y)))
val))

(let (str x y (i 0))
(setq str "
(24.0000,28.0000) .. controls (27.3100,28.0000) and (29.9800,25.3100) .. (29.9800,22.0000)
")
(print (replace-regexp-in-string "([0-9.]+,\.[0-9.]+)" 'my/rep str)))
#+END_SRC

#+RESULTS: latexdesc
:
: (12,14) .. controls (13.7,14) and (15,12.7) .. (15,11)
``````