Как напечатать числа с плавающей точкой в ​​указанном формате?

Произвольное число может быть легко преобразовано в число с плавающей запятой с некоторым количеством десятичных знаков. Например, используя (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.

Я хотел бы напечатать вложенное дерево, содержащее числа

Если вы хотите вывести любое число в виде числа с плавающей запятой, просто отправьте REALtype (комплексные числа с ненулевыми мнимыми частями не могут быть напечатаны, как вы хотите, поэтому я не рекомендую отправлять на 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

Обратите внимание, что поплавки имеют ограниченную точность - как обычно.

Другие вопросы по тегам