如何在lisp中以指定格式将数字打印为浮点数?

Posted

技术标签:

【中文标题】如何在lisp中以指定格式将数字打印为浮点数?【英文标题】:How to print numbers as floats with a specified format in lisp? 【发布时间】:2016-11-23 18:52:43 【问题描述】:

任意数字可以很容易地转换为带有一些小数的浮点数。例如,使用(format nil "~,2f" 6) 会得到"6.00"。但是有没有办法使用类似的浮点类型规范直接强制任意数字?即,输出一个数字,而不是一个字符串?或者,我试过(read-from-string (format nil "~,2f" 6)),但这不保留格式。

我想打印一个包含数字(以及其他 lisp 对象)的嵌套树,作为带有两位小数的浮点数。例如,无论 X 中表示的具体数字类型如何,打印输出可能看起来像 X -> (A 3.00 (7.10 B) (C 8.12) 0.75)。set-pprint-dispatch 用于这种输出还是格式足够?

【问题讨论】:

我认为您将数字与其印刷表示混淆了。 您的意思是要将整数强制转换为浮点数吗?如(float 6)=> 6.0? “保留格式”是什么意思?内存中的数字不包含任何格式。您可以在打印时以您想要的方式格式化任何数字。 @sds 是的,现在我知道你是对的。我真正想做的是打印一个不带引号的数字。我应该只使用 (format t "~,2f" 6) 而不是 (format nil "~,2f" 6)。感谢您的澄清。 @davypough,我建议编辑你的问题,明确表明你期待6.00,但你得到的是"6.00"——然后,如果你觉得你现在明白(format t...很舒服正在打印 6.00,而(format nil ... 正在返回字符串 "6.00",请继续写下答案并接受它,以供未来用户使用。 【参考方案1】:

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

由于漂亮打印调度表是在修改之前复制的,因此与浮点数关联的函数只能从 let-binding 内部调用。当WRITE 的返回值打印到 REPL 时,使用默认的调度表。您可以定义一个全局变量以避免每次需要时重新计算修改后的表。

请注意,如果您没有为:pretty 指定值,那么特殊的*PRINT-PRETTY* 变量将定义是否使用漂亮打印机。详情见22.2.1.4 Pretty Print Dispatch Tables。

我想打印一个包含数字的嵌套树

如果您想要将 任何数字 输出为浮点数,只需在 REAL 类型上调度(不能按您的需要打印具有非零虚部的复数,所以我不建议在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)

【讨论】:

此应用程序是摘要打印输出,因此效果很好。我在write 之前和之后添加了in-package 语句,以禁止打印非实数的包前缀;并将write 语句嵌入循环中,以在单独的行上打印输入树顶层中的每个项目。 (如果这些变化没有实际意义,请进一步评论。感谢您帮助整理我的想法。) 不客气,谢谢。您可以在本地绑定*package* 而不是使用in-package,这更简单,因为您不必显式恢复到以前的包,这可能容易出错。但我宁愿在 write 调用中将:escape 设置为 NIL 以避免打印包。见clhs.lisp.se/Body/v_pr_esc.htm#STprint-escapeST。您还可以为符号定义自定义漂亮的打印机功能,例如数字。【参考方案2】:

要强制数字为浮点数,请使用coercefloat

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

请注意,浮点数的精度有限 - 像往常一样。

【讨论】:

以上是关于如何在lisp中以指定格式将数字打印为浮点数?的主要内容,如果未能解决你的问题,请参考以下文章

如何在 x86(32 位)程序集中将无符号整数转换为浮点数?

Pyspark - ValueError:无法将字符串转换为浮点数/浮点()的无效文字

如何将表示为字符串的数字转换为浮点数

在 Netezza 中将带分数转换为浮点数

NEON 汇编代码,如何将 BYTE 转换为浮点数?

如何在 Java 中将整数转换为浮点数?