Convert a string consisting of a number from format "12345.6789" to "12/345.7"

Convert a string consisting of a number from format "12345.6789" to "12/345.7"

jakob.holmquistGRCUL
Enthusiast Enthusiast
875 Views
6 Replies
Message 1 of 7

Convert a string consisting of a number from format "12345.6789" to "12/345.7"

jakob.holmquistGRCUL
Enthusiast
Enthusiast

Hello!

I'm trying to convert a number (in string format) to the format "abc/def.x"

It's hard to explain the format with words and probably easier to understand with examples, so here are a few examples:

1532.645 should become 1/532.6

3054 should become 3/054.0

5 should be 0/005.0

127.99 should become 0/128.0

 

So basically, the digits before the / sign should be the original number divided by 1000, rounded down. If the number is less than 1000, there should be a 0 before the / sign.

 

The orignal number should then be rounded up to 1 decimal point, even when the number is even it must have exactly one decimal.

 

There must always be three digits (and one decimal point) after the / sign. Add zeros if needed. For example: 1 should become 0/001.0 and the number 45.69 should become 0/045.7

 

I have a rough idea of dividing the number into substrings and combining them with strcat. To get the digits before the / sign simply divide the number by 1000 and make it integer (by using fix). Add the string "/". But I don't know how to get the last 3 digits (and the decimal point) if the original number has 4 digits or more. Anyone have in idea how to solve this?

 

 

Code so far:  

(setq original_number 123456.789)
(setq text_1000 (/ original_number 1000))
(setq text_1000 (fix text_1000))

(setq text_100 ??????????????)

(setq final_text (strcat (itoa text_1000) "/" (itoa text_100))

 

0 Likes
876 Views
6 Replies
Replies (6)
Message 2 of 7

CodeDing
Advisor
Advisor
Accepted solution

@jakob.holmquistGRCUL ,

 

Hmm, interesting request. This seems to be up and working for me! 

EDIT:

No negative numbers are handled in this function though. But we could account for that if needed!

(defun str2slash (str / n len tmp cnt)
  ;; str - string, of real # [to convert to slashed #, to one decimal: "1/234/567.9"]
  (if (and (setq n (distof str 2))
           (setq n (rtos n 2 1))
           (setq n (vl-string->list n))
           (setq len (length n))
      );and
    (cond
      ((= 2 len) (vl-list->string (append '(48 47 48 48 48) n)))
      ((= 3 len) (vl-list->string (append '(48 47 48 48) n)))
      ((= 4 len) (vl-list->string (append '(48 47 48) n)))
      ((= 5 len) (vl-list->string (append '(48 47) n)))
      ((> len 5) (setq n (reverse n) tmp (list (cadr n) (car n)) cnt -1 n (cdr n))
        (vl-list->string
          (while (setq n (cdr n))
            (if (= 3 (setq cnt (1+ cnt)))
              (setq cnt 0 tmp (cons 47 tmp))
            );if
            (setq tmp (cons (car n) tmp))
          );while
        );vl-list->string
      );cond 5
    );cond
  );if
);defun

 

Samples (works on integers also):

 

Command: (str2slash "1234567890.456")
"1/234/567/890.5"
Command: (str2slash "890.456")
"0/890.5"
Command: (str2slash "90.444")
"0/090.4"
Command: (str2slash "0.444")
"0/000.4"
Command: (str2slash "123")
"0/123.0"
Command: (str2slash "0")
"0/000.0"
Command: (str2slash "123456")
"123/456.0"

 

 

Best,

~DD

Message 3 of 7

CodeDing
Advisor
Advisor
Accepted solution

 

This version handles negatives!

 

(defun str2slash (str / n isNeg len tmp cnt)
  ;; str - string, of real # to convert to slashed #: "1/234/567.9"
  (if (and (setq n (distof str 2))
           (setq isNeg (minusp n) n (rtos n 2 1))
           (setq n (if isNeg (cdr (vl-string->list n)) (vl-string->list n)))
           (setq len (length n))
      );and
    (cond
      ((= 2 len) (vl-list->string (append (if isNeg '(45 48 47 48 48 48) '(48 47 48 48 48)) n)))
      ((= 3 len) (vl-list->string (append (if isNeg '(45 48 47 48 48) '(48 47 48 48)) n)))
      ((= 4 len) (vl-list->string (append (if isNeg '(45 48 47 48) '(48 47 48)) n)))
      ((= 5 len) (vl-list->string (append (if isNeg '(45 48 47) '(48 47)) n)))
      ((> len 5) (setq n (reverse n) tmp (list (cadr n) (car n)) cnt -1 n (cdr n))
        (vl-list->string
          (progn
            (while (setq n (cdr n))
              (if (= 3 (setq cnt (1+ cnt)))
                (setq cnt 0 tmp (cons 47 tmp))
              );if
              (setq tmp (cons (car n) tmp))
            );while
            (if isNeg (cons 45 tmp) tmp)
          );progn
        );vl-list->string
      );cond 5
    );cond
  );if
);defun

 

Best,

~DD

Message 4 of 7

pbejse
Mentor
Mentor
Accepted solution

@jakob.holmquistGRCUL wrote:

...

1532.645 should become 1/532.6, 3054 should become 3/054.0 ,5 should be 0/005.0

127.99 should become 0/128.0

This is very simlar to adding "," (comma) to represent thousands,hundred thousands...

Will we even consider negative numbers here?

(Defun _Slasher (n / str lead trail slashed s)
  (setq	pref (if (minusp n) "-" "")
	str	(rtos (setq n (abs n)) 2 1)
	lead	(vl-filename-base str)
	s	(strlen lead)
	trail	(vl-filename-extension str)
	slashed	""
  )
  (if (< n 1000)
    (setq lead (strcat (nth (1- s) '("000" "00" "0")) lead) s (strlen lead))
  )
  (While (> s 3)
    (setq slashed (strcat "/" (substr lead (setq s (- s 2)) 3)
			  slashed ) s	 (1- s))
  	)
  (strcat pref (substr lead 1 s) slashed trail)
)

_$ (_Slasher 1532.645)
"1/532.6"
_$ (_Slasher 3054)
"3/054.0"
_$ (_Slasher 5)
"0/005.0"
_$ (_Slasher 127.99)
"0/128.0"

_$ (_Slasher 123456.789)
"123/456.8"

 

HTH

 

Message 5 of 7

hak_vz
Advisor
Advisor
Accepted solution

 

(defun foo (str / pref a b c left n)
	(cond
		((=(type str) 'STR)
			(if (= (substr str 1 1) "-") (setq pref "-")(setq pref ""))
			(setq str (rtos (abs (atof str))2 8))
			(if (not (setq n(vl-string-position (ascii ".") str)))(setq str (strcat str ".0")))
			(setq
				n(vl-string-position (ascii ".") str)
				left (substr str 1 n) 
				c (rtos(atof(substr str (1+ n)))2 1)
				a (/ (atoi left) 1000)
				b (- (atoi left) (* a 1000))
				a (itoa a)
				b (itoa b)
			)
			(if (>(strlen c) 1)(setq c (substr c 3)))
			(if (=(strlen b) 1)(setq b(strcat "00" b)))
			(if (=(strlen b) 2)(setq b(strcat "0" b)))
			(strcat pref a "/" b  "." c)
		)
	)
)
Command: (mapcar 'foo '("0" "5" "-65.005" "455.5" "2345.6789" "-12525.356" "112457.45"))
("0/000.0" "0/005.0" "-0/065.0" "0/455.5" "2/345.7" "-12/525.4" "112/457.5")

 

 

 

Miljenko Hatlak

EESignature

Did you find this post helpful? Feel free to Like this post.
Did your question get successfully answered? Then click on the ACCEPT SOLUTION button.
Message 6 of 7

john.uhden
Mentor
Mentor
Accepted solution

@jakob.holmquistGRCUL 

That's exactly what my @formatsta functon  does, which adds a "+" character

So, I just changed the name and one character "+" to "/" and here ya go...

 

(defun @Format/ (# xp prec / n sign str)
  ;; where:
  ;;  # = real or integer or string which will be converted to a number
  ;;  xp = exponent of 10 to specify how many numeric charcters between "/" and "."
  ;;  prec = decimal precision
  (if (= (type #) 'STR)(setq # (read #)))
  (setq n (expt 10.0 xp) dimzin (getvar "dimzin"))
  (setvar "dimzin" 0)
  (setq sign (if (minusp #) "-" ""))
  (setq # (abs #))
  (setq str1 (strcat sign (itoa (fix (/ # n))) "/"))
  (setq str2 (rtos (* n (rem (/ # n) 1)) 2 prec))
  (repeat (max (- xp (strlen str2))(- xp (vl-string-position 46 str2)))
    (setq str2 (strcat "0" str2))
  )
  (setvar "dimzin" dimzin)
  (strcat str1 str2)
)

 

John F. Uhden

Message 7 of 7

jakob.holmquistGRCUL
Enthusiast
Enthusiast

Wow, thanks everyone, so many helpful answers! 🙂 These worked perfectly, many thanks!

0 Likes