Как напечатать числа с плавающей точкой в указанном формате?
Произвольное число может быть легко преобразовано в число с плавающей запятой с некоторым количеством десятичных знаков. Например, используя (format nil "~,2f" 6)
дает "6.00"
, Но есть ли способ напрямую привести произвольное число, используя аналогичную спецификацию типа float; т.е. вывод числа, а не строки? Поочередно я пробовал (read-from-string (format nil "~,2f" 6))
, но это не сохраняет форматирование.
Я хотел бы напечатать вложенное дерево, содержащее числа (вместе с другими объектами lisp), как плавающие с двумя десятичными знаками. Например, распечатка может выглядеть X -> (A 3.00 (7.10 B) (C 8.12) 0.75)
независимо от конкретных типов чисел, представленных в X. Используется ли set-pprint-dispatch для этого вида вывода или достаточно ли формата?
2 ответа
Используется ли set-pprint-dispatch для этого вида вывода или формат достаточно?
Давай попробуем с SET-PPRINT-DISPATCH
:
CL-USER> (let ((*print-pprint-dispatch* (copy-pprint-dispatch)))
(set-pprint-dispatch 'float (lambda (s f) (format s "~,2f" f)))
(write '(A 3.00 (7.10 B) (C 8.12) 0.75) :pretty t))
(A 3.00 (7.10 B) (C 8.12) 0.75) ;; standard output
(A 3.0 (7.1 B) (C 8.12) 0.75) ;; result printed by the REPL
Поскольку таблица отправки pretty-print копируется перед изменением, функция, связанная с плавающей точкой, вызывается только из let-привязки. Когда возвращаемое значение WRITE
печатается в REPL, используется таблица отправки по умолчанию. Вы можете определить глобальную переменную, чтобы избежать пересчета измененной таблицы каждый раз, когда вам это нужно.
Обратите внимание, что если вы не дадите значение для :pretty
тогда особенный *PRINT-PRETTY*
Переменная определяет, используется ли симпатичный принтер или нет. Подробнее см. 22.2.1.4 Таблицы отправки Pretty Print.
Я хотел бы напечатать вложенное дерево, содержащее числа
Если вы хотите вывести любое число в виде числа с плавающей запятой, просто отправьте REAL
type (комплексные числа с ненулевыми мнимыми частями не могут быть напечатаны, как вы хотите, поэтому я не рекомендую отправлять на number
). Любое необходимое принуждение произойдет неявно:
(let ((*print-pprint-dispatch* (copy-pprint-dispatch)))
(set-pprint-dispatch 'real (lambda (s f) (format s "~,2f" f)))
(write '(A 3 (7.1d0 B) (C 203/25) #C(3/4 0)) :pretty t))
... пишет:
(A 3.00 (7.10 B) (C 8.12) 0.75)
Чтобы заставить числа плавать числа используйте coerce
или же float
:
CL-USER 121 > (float 2/3 1.0s0)
0.6666667
CL-USER 122 > (float 2/3 1.0d0)
0.6666666666666666D0
CL-USER 123 > (coerce 2/3 'double-float)
0.6666666666666666D0
Обратите внимание, что поплавки имеют ограниченную точность - как обычно.