在常见的Lisp中,如何格式化浮点并指定分组,分组char和小数点分隔符char [英] In common lisp how can I format a floating point and specify grouping, group char and decimal separator char
问题描述
假设我有浮点数 1234.9
我想将其格式化为 1.234,90
是否存在格式指令组合? 〜D
可以处理分组和组char,只能处理整数。 〜F
根本无法处理分组。据我所知,没有人可以将小数点从。
更改为,
Is there a format directive combination for that? ~D
,which can handle the grouping and the group char, handles only integers. ~F
doesn't handle grouping at all. And none as far as I know can change the decimal point from .
to ,
我看到的唯一解决方案是对整数部分数字分组使用〜D
并将其与串联,
和小数部分。有更好的主意吗?
The only solution I see is to use ~D
for the integer part digit grouping and concatenate it with ,
and the decimal part. Any better ideas?
推荐答案
您可以定义一个用代字号-斜杠调用的函数,其他大多数答案已经完成,但为了获得类似于〜F的输出,但注入了逗号,并替换了小数点,我认为最好调用get〜F产生的输出,然后对其进行修改并将其写入字符串。使用实用程序 inject-逗号可以按指定的间隔向字符串添加逗号,这是一种实现方法。这是指令函数:
You can define a function to be called with tilde-slash, which most of the other answers have already done, but in order to get output similar to ~F, but with comma chars injected, and with the decimal point replaced, I think it's best to call get the output produced by ~F, and then modify it and write it to the string. Here's a way to do that, using a utility inject-comma that adds a comma character at specified intervals to a string. Here's the directive function:
(defun print-float (stream arg colonp atp
&optional
(point-char #\.)
(comma-char #\,)
(comma-interval 3))
"A function for printing floating point numbers, with an interface
suitable for use with the tilde-slash FORMAT directive. The full form
is
~point-char,comma-char,comma-interval/print-float/
The point-char is used in place of the decimal point, and defaults to
#\\. If : is specified, then the whole part of the number will be
grouped in the same manner as ~D, using COMMA-CHAR and COMMA-INTERVAL.
If @ is specified, then the sign is always printed."
(let* ((sign (if (minusp arg) "-" (if (and atp (plusp arg)) "+" "")))
(output (format nil "~F" arg))
(point (position #\. output :test 'char=))
(whole (subseq output (if (minusp arg) 1 0) point))
(fractional (subseq output (1+ point))))
(when colonp
(setf whole (inject-comma whole comma-char comma-interval)))
(format stream "~A~A~C~A"
sign whole point-char fractional)))
以下是一些示例:
(progn
;; with @ (for sign) and : (for grouping)
(format t "~','.2@:/print-float/ ~%" 12345.6789) ;=> +1.23.45,679
;; with no @ (no sign) and : (for grouping)
(format t "~'.'_3:/print-float/ ~%" 12345.678) ;=> 12_345.678
;; no @ (but sign, since negative) and : (for grouping)
(format t "~'.'_3:/print-float/ ~%" -12345.678) ;=> -12_345.678
;; no @ (no sign) and no : (no grouping)
(format t "~'.'_3@/print-float/ ~%" 12345.678)) ;=> +12345.678 (no :)
以下是 coredump-的答案,它实际上帮助我发现了一个带有负数的错误:
Here are the examples from coredump-'s answer, which actually helped me catch a bug with negative numbers:
CL-USER> (loop for i in '(1034.34 -223.12 -10.0 10.0 14 324 1020231)
do (format t "~','.:/print-float/~%" i))
1.034,34
-223,12
-10,0
10,0
14,0
324,0
1.020.231,0
NIL
这里是注入逗号,其中包括一些示例:
Here's inject-comma, with some examples:
(defun inject-comma (string comma-char comma-interval)
(let* ((len (length string))
(offset (mod len comma-interval)))
(with-output-to-string (out)
(write-string string out :start 0 :end offset)
(do ((i offset (+ i comma-interval)))
((>= i len))
(unless (zerop i)
(write-char comma-char out))
(write-string string out :start i :end (+ i comma-interval))))))
(inject-comma "1234567" #\, 3)
;;=> "1,234,567"
(inject-comma "1234567" #\. 2)
;;=> "1.23.45.67"
这篇关于在常见的Lisp中,如何格式化浮点并指定分组,分组char和小数点分隔符char的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!