浮点数适用于表示非整数数值。其取值范围与你所用机器上 C 语言的 double 数据类型一致。在几乎所有 Emacs 支持的计算机上,浮点数均采用 IEEE binary64(双精度)浮点格式—— 该格式由 IEEE Std
754-2019 标准化,David Goldberg 的论文 “What Every Computer Scientist Should Know About Floating-Point Arithmetic” 也对其有深入探讨。现代平台上的浮点运算基本遵循 IEEE-754 标准,但部分系统(尤其是 32 位 x86 架构)的运算结果可能无法保证正确舍入。
在某些老旧计算机系统上,Emacs 可能不使用 IEEE 浮点数。我们已知有一个这样的系统:运行 NetBSD 并使用 GCC 10.4.0 的 VAX 计算机,Emacs 可以正常运行,但不遵循 IEEE-754,而是改用 VAX 的 ‘D_Floating’ 格式。基于 IBM System/370 的大型机及其 XL/C 编译器也支持十六进制浮点数格式,但 Emacs 尚未在这类配置下编译构建过。
浮点数的读取语法要求必须包含小数点、指数,或两者同时具备。数值及其指数前可添加可选符号(‘+’ 或 ‘-’)。例如,‘1500.0’、‘+15e2’、‘15.0e+2’、‘+1500000e-3’ 和 ‘.15e4’ 是表示数值 1500 的五种浮点数写法,它们完全等价。与 Common Lisp 一致,Emacs Lisp 规定:对于不含指数的浮点数,小数点后必须至少有一位数字;因此 ‘1500.’ 会被解析为整数,而非浮点数。
在 = 等数值比较操作中,Emacs Lisp 将 -0.0 视为与普通零在数值上相等。这一行为遵循 IEEE 浮点标准 —— 该标准规定,即便其他操作可区分 -0.0 和 0.0,二者在数值层面仍相等。
IEEE 浮点标准支持将正无穷和负无穷作为浮点值,还定义了一类名为 NaN (即 “not a number非数值”)的值;当数值函数无合法计算结果时,会返回此类值。例如,(/ 0.0 0.0) 会返回 NaN。NaN 在数值上永不等于任何值,甚至不等于其自身。NaN 包含符号和尾数,若两个 NaN 的符号与尾数均一致,非数值函数会将它们判定为相等。NaN 的尾数及其字符串表示形式均依赖于具体机器。
当涉及 NaN 和带符号零(0.0 或 −0.0)时,eql、equal、sxhash-eql、sxhash-equal 和 gethash 这类非数值函数判断的是值是否不可区分,而非数值上是否相等。例如:当 x 和 y 是同一个 NaN 时,(equal x y) 返回 t,而 (= x y) 进行数值比较,返回 nil;反之,(equal 0.0 -0.0) 返回 nil,而 (= 0.0 -0.0) 返回 t。
以下是这些特殊浮点值的读取语法:
无穷大:‘1.0e+INF’ 和 ‘-1.0e+INF’
非数值(NaN):‘0.0e+NaN’ 和 ‘-0.0e+NaN’
在不支持 IEEE 浮点运算的老旧系统中,无穷大和 NaN 不可用。例如在 1980 年左右的 VAX 机器上,Lisp 会将 ‘1.0e+INF’ 解析为一个很大但有限的浮点数,将 ‘0.0e+NaN’ 解析为其他非数值型 Lisp 对象,若将其用于数值运算会触发错误。
以下是专门用于处理浮点数的函数:
该谓词函数的返回值规则:若浮点类型参数 x 是 NaN,返回 t;否则返回 nil。
该函数返回一个 cons 单元格 (s . e),其中 s 和 e 分别是浮点数 x 的尾数(significand)和指数(exponent)。
若 x 是有限值:s 是介于 0.5(包含)和 1.0(不包含)之间的浮点数,e 是整数,且满足 x = s * 2**e。 若 x 是 0 或无穷大:s 与 x 相等。 若 x 是 NaN:s 也为 NaN。 若 x 是 0,e 为 0。
给定数值型尾数 s 和整数型指数 e,该函数返回浮点数结果为 s * 2**e。
该函数将 x2 的符号复制到 x1 的数值上,并返回结果。x1 和 x2 必须均为浮点类型。
该函数返回 x 的二进制指数。更精确地说: 若 x 是有限非零值,返回值为 \(|x|\) 以 2 为底的对数,向下取整为整数; 若 x 是 0 或无穷大,返回值为无穷大; 若 x 是 NaN,返回值为 NaN。
(logb 10)
⇒ 3
(logb 10.0e20)
⇒ 69
(logb 0)
⇒ -1.0e+INF