Chapter 8. 数字操作
本章介绍了 Chez Scheme 对数字对象上的标准操作集的扩展。参见"The Scheme Programming Language, 第 4 版", 第 6 章,或 R6RS 中对数字对象上标准操作的介绍。
Chez Scheme 支持全部 Scheme 数字类型,包括精确和不精确整数,有理数,实数,及复数。并使用了一系列表示形式支持这些数据类型:
Fixnums
在 fixnum 范围内表示精确整数(参见 most-negative-fixnum
和 most-positive-fixnum
)。字符串,向量或 fxvector 的长度均被限定为 fixnum.
Bignums 表示 fixnum 范围外的任意精度的精确整数。
Ratnums 表示任意精度的精确有理数。每个有理数包含一个精确整数分子(fixnum 或 bignum)和一个精确整数分母。分数总是被约分为最简形式,分母从不为 1,而分子永不会为 0.
Flonums 表示不精确的实数。Flonums 是 IEEE 64 位浮点数。(由于 flonums 不能表示无理数,所有不精确的实数实际只是指有理数,虽然它们可能近似于无理数的数值)。
Exact complexnums 表示精确的复数。每个复数包含一个精确有理数(fixnum, bignum, 或 ratnum)的实部,和一个精确有理数的虚部。
Inexact complexnums 表示不精确的复数。每个不精确的复数包含一个浮点数实部和一个浮点数虚部。
大多数数字只能以一种方式表示;不过,实数有时会表示为虚部为 0 的不精确复数。
Chez Scheme 对数字对象的语法进行了扩展,包括 2 至 36 的任意基数,非十进制的浮点数,科学表示法,以及 IEEE 无穷数和 NAN(NAN 是 "not-a-number" 的缩写)的打印形式。
任意基数由前缀 #nr
指定, n
的范围是 2 至 36. 大于 9 的数字用字母 a
至 z
指定(大写小写均可)。例如, ~#2r101 ~ 是 510, 而 ~#36rZ ~ 是 3510.
对于较大的基数,对于特定字母的解读会出现歧义,例如, e
, 作为数字还是作为指数指示符;在这类情况下,字母被当作一个数字。例如,在 #x3.2e5
中, e
被解读为一个数字,而不作为指数标记。而在 3.2e5
中, e
则被当作指数标记。
IEEE 无穷数被打印为+inf.0 和-inf.0, 而 IEEE NANs 被打印为 +nan.0 或-nan.0. (+nan.0 被用作所有 NANs 的输出)
(/ 1.0 0.0) => +inf.0
(/ 1.0 -0.0) => -inf.0
(/ 0.0 0.0) => +nan.0
(/ +inf.0 -inf.0) => +nan.0
本章第 1 节介绍了特定类型的数字类型谓词。8.2 至 8.4 节介绍了应用于 fixnums, flonums, 和不精确的复数(flonums 和/或不精确的 complexnums)上的快速的,类型专用的数字操作。专用于 fixnum 的版本,应只用于程序员确定操作数和结果都会是 fixnum 时,即,整数在范围 (most-negative-fixnum)
至 (most-positive-fixnum)
之间时(两端均包含)。专用于 flonum 的版本,应只用于输入和输出确定为 flonum 时。flonum/complexnum 混合版本,应只用于输入确定为 flonum 或不精确的 complexnum 时。8.5 节介绍了支持把精确整数作为比特集合或序列的,任意精度和专用于 fixnum 的操作。8.6 节介绍了随机数生成,8.7 节介绍了其余各种数字操作。
Section 8.1. 数字类型谓词
R6RS 区分了两种特殊的数字对象:fixnum 和 flonum. Chez Scheme 进一步区分了 bignum(fixnum 范围之外的精确整数)和 ratnum(精确整数的比值)。它同时也提供了一个识别 cflonum 的谓词,其为 flonum 或不精确的复数。
procedure: (bignum? obj)
返回: 如果 obj
是 bignum,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
(bignum? 0) => #f
(bignum? (most-positive-fixnum)) => #f
(bignum? (most-negative-fixnum)) => #f
(bignum? (* (most-positive-fixnum) 2)) => #t
(bignum? 3/4) => #f
(bignum? 'a) => #f
procedure: (ratnum? obj)
返回: 如果 obj
是 ratnum,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
(ratnum? 0) => #f
(ratnum? (* (most-positive-fixnum) 2)) => #f
(ratnum? 3/4) => #t
(ratnum? -10/2) => #f
(ratnum? -11/2) => #t
(ratnum? 'a) => #f
procedure: (cflonum? obj)
返回: 如果 obj
是不精确的 complexnum 或 flonum,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
(cflonum? 0) => #f
(cflonum? 0.0) => #t
(cflonum? 3+4i) => #f
(cflonum? 3.0+4i) => #t
(cflonum? +i) => #f
(cflonum? +1.0i) => #t
Section 8.2. Fixnum 操作
专用于 fixnum 的过程,通过会检查它们的输入和输出(需要时),但编译器在优化级别 3 下生成的代码,大多数情况下不执行这些检查。
procedure: (most-positive-fixnum)
returns: 系统支持的最大正 fixnum
procedure: (most-negative-fixnum)
returns: 系统支持的最大负 fixnum
libraries: (chezscheme)
这些过程和 R6RS 中的 greatest-fixnum
和 least-fixnum
过程一样。
procedure: (fx= fixnum1 fixnum2 …)
procedure: (fx< fixnum1 fixnum2 …)
procedure: (fx> fixnum1 fixnum2 …)
procedure: (fx<= fixnum1 fixnum2 …)
procedure: (fx>= fixnum1 fixnum2 …)
返回: 如果关系成立,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
谓词 fx=在其实参相等时返回#t。谓词 fx<在其实参单调递增时返回#t,即,每个实参都大于它前一个实参,而 fx>在其实参单调递减时返回#t。谓词 fx<=在其实参单调非递减时返回#t,即,每个实参不小于它前一个实参,而 fx>=在其实参单调非递增时返回#t。只传入一个实参时,这些谓词均返回#t。
这些过程与 R6RS 中的过程 fx=?, fx<?, fx>?, fx<=?, 和 fx>=?类似,除了 R6RS 中的过程需要 2 个或更多参数,以及它们的名称中都有 "?" 后缀以外。
(fx= 0) => #t
(fx= 0 0) => #t
(fx< (most-negative-fixnum) 0 (most-positive-fixnum)) => #t
(let ([x 3]) (fx<= 0 x 9)) => #t
(fx<= 0 3 3) => #t
(fx>= 0 0 (most-negative-fixnum)) => #t
procedure: (fxnonpositive? fixnum)
返回: 如果 fixnum 不大于 0,则为 #t
, 否则为 #f
.
procedure: (fxnonnegative? fixnum)
返回: 如果 fixnum 不小于 0,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
fxnonpositive?等价于(lambda (x) (fx<= x 0)), 而 fxnonnegative?等价于(lambda (x) (fx>= x 0)).
(fxnonpositive? 128) => #f
(fxnonpositive? 0) => #t
(fxnonpositive? -1) => #t
(fxnonnegative? -65) => #f
(fxnonnegative? 0) => #t
(fxnonnegative? 1) => #t
procedure: (fx+ fixnum …)
returns: 实参 fixnum …之和
libraries: (chezscheme)
When called with no arguments, fx+ returns 0. 不带参数调用时,fx+返回 0.
(fx+) => 0
(fx+ 1 2) => 3
(fx+ 3 4 5) => 12
(apply fx+ '(1 2 3 4 5)) => 15
procedure: (fx- fixnum1 fixnum2 …)
returns: 一个 fixnum
libraries: (chezscheme)
调用时若只传入一个实参,fx-返回 fixnum1 的负值。即,(fx- fixnum1)相当于(fx- 0 fixnum1).
调用时若传入 2 个以上的实参,fx-返回从 fixnum1 中减去数字 fixnum2 …之和的结果。
(fx- 3) => -3
(fx- 4 3) => 1
(fx- 4 3 2 1) => -2
procedure: (fx* fixnum …)
returns: 参数 fixnum …的乘积
libraries: (chezscheme)
不带参数调用时,fx*返回 1.
(fx*) => 1
(fx* 1 2) => 2
(fx* 3 -4 5) => -60
(apply fx* '(1 -2 3 -4 5)) => 120
procedure: (fx/ fixnum1 fixnum2 …)
returns: 参见后面的解释
libraries: (chezscheme)
调用时若只传入一个实参,fx/返回 fixnum1 的倒数。即,(fx/ fixnum1)相当于(fx/ 1 fixnum1).
调用时若传入 2 个以上的实参,fx/ 返回 fixnum1 除以其余实参 fixnum2 …的乘积的结果。
(fx/ 1) => 1
(fx/ -17) => 0
(fx/ 8 -2) => -4
(fx/ -9 2) => -4
(fx/ 60 5 3 2) => 2
procedure: (fx1+ fixnum)
procedure: (fx1- fixnum)
returns: fixnum 加 1 或 fixnum 减 1
libraries: (chezscheme)
(define fxplus
(lambda (x y)
(if (fxzero? x)
y
(fxplus (fx1- x) (fx1+ y)))))
(fxplus 7 8) => 15
fx1+ 和 fx1- 可依如下定义:
(define fx1+ (lambda (x) (fx+ x 1)))
(define fx1- (lambda (x) (fx- x 1)))
procedure: (fxquotient fixnum1 fixnum2 …)
returns: 参见后面的解释
libraries: (chezscheme)
fxquotient 和 fx/一样。参见上面关于 fx/的介绍。
procedure: (fxremainder fixnum1 fixnum2)
returns: fixnum1 除以 fixnum2 的 fixnum 余数
libraries: (chezscheme)
fxremainder 结果的符号与 fixnum1 相同。
(fxremainder 16 4) => 0
(fxremainder 5 2) => 1
(fxremainder -45 7) => -3
(fxremainder 10 -3) => 1
(fxremainder -17 -9) => -8
procedure: (fxmodulo fixnum1 fixnum2)
returns: fixnum1 和 fixnum2 的 fixnum 模数
libraries: (chezscheme)
fxmodulo 结果的符号与 fixnum2 相同。
(fxmodulo 16 4) => 0
(fxmodulo 5 2) => 1
(fxmodulo -45 7) => 4
(fxmodulo 10 -3) => -2
(fxmodulo -17 -9) => -8
procedure: (fxabs fixnum)
returns: fixnum 的绝对值
libraries: (chezscheme)
(fxabs 1) => 1
(fxabs -1) => 1
(fxabs 0) => 0
Section 8.3. Flonum 操作
不精确的实数通常以 flonum 表示。flonum 是一个单一的 64 位双精度浮点数。本节介绍针对 flonum 的操作,其中大多数接受 flonum 类型的实参,并返回 flonum 类型的值。大多数情况下,这些操作是内联编码或是在不进行实参类型检查的优化级别 3 下编码为机器语言子程序;全面的类型检查是在更低的优化级别下执行的。专用于 flonum 的过程名称带有前缀"fl",以区分于它们的通用版本。
不精确的实数也可以用虚部为 0 的不精确 complexnums 表示,这种表示形式不可用于 flonum 专用操作符的输入。然而,这些数字只会在显式调用 fl-make-rectangular, make-rectangular, 或 make-polar 时,或通过极坐标或直角坐标形式的数字输入,由涉及虚部非 0 的复数操作中生成。
procedure: (flonum->fixnum flonum)
returns: flonum 的 fixnum 表示形式(被截短的)
libraries: (chezscheme)
flonum 被截短后的值必须落在 fixnum 范围内。flonum->fixnum 是一个精确值的限定版本,会把任何数字表示转化为它的精确等价版本。
(flonum->fixnum 0.0) => 0
(flonum->fixnum 3.9) => 3
(flonum->fixnum -2.2) => -2
procedure: (fl= flonum1 flonum2 …)
procedure: (fl< flonum1 flonum2 …)
procedure: (fl> flonum1 flonum2 …)
procedure: (fl<= flonum1 flonum2 …)
procedure: (fl>= flonum1 flonum2 …)
返回: 如果关系成立,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
谓词 fl=在其实参相等时返回#t。谓词 fl<在其实参单调递增时返回#t,即,每个实参都大于它前一个实参,而 fl>在其实参单调递减时返回#t。谓词 fl<=在其实参单调非递减时返回#t,即,每个实参不小于它前一个实参,而 fl>=在其实参单调非递增时返回#t。只传入一个实参时,这些谓词均返回#t。
IEEE NANs 不具有可比较性,即,涉及 NANs 的比较总是返回#f.
这些过程与 R6RS 中的过程 fl=?, fl<?, fl>?, fl<=?, 和 fl>=?类似,除了 R6RS 中的过程需要 2 个或更多参数,以及它们的名称中都有 "?" 后缀以外。
(fl= 0.0) => #t
(fl= 0.0 0.0) => #t
(fl< -1.0 0.0 1.0) => #t
(fl> -1.0 0.0 1.0) => #f
(fl<= 0.0 3.0 3.0) => #t
(fl>= 4.0 3.0 3.0) => #t
(fl< 7.0 +inf.0) => #t
(fl= +nan.0 0.0) => #f
(fl= +nan.0 +nan.0) => #f
(fl< +nan.0 +nan.0) => #f
(fl> +nan.0 +nan.0) => #f
procedure: (flnonpositive? fl)
返回: 如果 fl 不大于 0,则为 #t
, 否则为 #f
.
procedure: (flnonnegative? fl)
返回: 如果 fl 不小于 0,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
flnonpositive?等价于(lambda (x) (fl<= x 0.0)), 而 flnonnegative?等价于(lambda (x) (fl>= x 0.0)).
虽然 flonum 的表示形式区分-0.0 和+0.0,但都判定为非负且非正。
(flnonpositive? 128.0) => #f
(flnonpositive? 0.0) => #t
(flnonpositive? -0.0) => #t
(flnonpositive? -1.0) => #t
(flnonnegative? -65.0) => #f
(flnonnegative? 0.0) => #t
(flnonnegative? -0.0) => #t
(flnonnegative? 1.0) => #t
(flnonnegative? +nan.0) => #f
(flnonpositive? +nan.0) => #f
(flnonnegative? +inf.0) => #t
(flnonnegative? -inf.0) => #f
procedure: (decode-float x)
returns: 参见下文
libraries: (chezscheme)
x 必须是 flonum. decode-float 返回一个包含 3 个整数元素的向量,m, e, 和 s, 满足 x = sm2e. 它主要是用于打印浮点数。
(decode-float 1.0) => #(4503599627370496 -52 1)
(decode-float -1.0) => #(4503599627370496 -52 -1)
(define slow-identity
(lambda (x)
(inexact
(let ([v (decode-float x)])
(let ([m (vector-ref v 0)]
[e (vector-ref v 1)]
[s (vector-ref v 2)])
(* s m (expt 2 e)))))))
(slow-identity 1.0) => 1.0
(slow-identity -1e20) => -1e20
procedure: (fllp flonum)
returns: 参见下文
libraries: (chezscheme)
fllp 返回一个 12 位整数,由指数加上一个 flonum(ieee 64 位浮点数)的最高表示位组成。它可以用于快速计算这个数的对数的近似值。
(fllp 0.0) => 0
(fllp 1.0) => 2046
(fllp -1.0) => 2046
(fllp 1.5) => 2047
(fllp +inf.0) => 4094
(fllp -inf.0) => 4094
(fllp #b1.0e-1111111111) => 1
(fllp #b1.0e-10000000000) => 0
Section 8.4. 不精确复数的操作
本节介绍的过程提供了创建和操作不精确复数的机制。虚部非 0 的不精确复数表示为不精确的 complexnums. 不精确的 complexnum 包含 2 个 64 位双精度浮点数。虚部为 0 的不精确复数(即, 不精确实数)可以表示为不精确 complexnums 或 flonums. 本节介绍的操作接受任何不精确 complexnum 和 flonum(合称为"cflonums")实参的组合。
大多数情况下,这些操作在优化级别 3 执行最少化的类型检查;在更低的优化级别才会执行全面的类型检查。不精确复数过程的名称以前缀 "cfl" 开始,以区分于它们对应的通用版本。
procedure: (fl-make-rectangular flonum1 flonum2)
returns: 一个不精确 complexnum
libraries: (chezscheme)
通过 fl-make-rectangular 生成的不精确 complexnum,实部等于 flonum1, 而虚部等于 flonum2.
(fl-make-rectangular 2.0 -3.0) => 2.0-3.0i
(fl-make-rectangular 2.0 0.0) => 2.0+0.0i
(fl-make-rectangular 2.0 -0.0) => 2.0-0.0i
procedure: (cfl-real-part cflonum)
returns: cflonum 的实部
procedure: (cfl-imag-part cflonum)
returns: cflonum 的虚部
libraries: (chezscheme)
(cfl-real-part 2.0-3.0i) => 2.0
(cfl-imag-part 2.0-3.0i) => -3.0
(cfl-imag-part 2.0-0.0i) => -0.0
(cfl-imag-part 2.0-inf.0i) => -inf.0
procedure: (cfl= cflonum …)
返回: 如果实参相等,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
(cfl= 7.0+0.0i 7.0) => #t
(cfl= 1.0+2.0i 1.0+2.0i) => #t
(cfl= 1.0+2.0i 1.0-2.0i) => #f
procedure: (cfl+ cflonum …)
procedure: (cfl* cflonum …)
procedure: (cfl- cflonum1 cflonum2 …)
procedure: (cfl/ cflonum1 cflonum2 …)
returns: 一个 cflonum
libraries: (chezscheme)
这些过程计算不精确复数数值的和,差,积或商,不论这些数值是以 flonums 表示,或以不精确 complexnums 表示。例如,如果 cfl+收到 2 个 flonum 实参 a 和 b,它返回它们的和 a + b; 在这种情况下,它和 fl+ 的行为一样。若 2 个实参为不精确 complexnum a + bi 和 c + di, 它返回和 (a + c) + (b + d)i. 若 1 个实参为 flonum a,而另一个为不精确 complexnum c + di, cfl+ 返回 (a + c) + di.
当传入 0 个实参,cfl+ 返回 0.0,而 cfl* 返回 1.0. 当传入 1 个实参,cfl- 返回实参的加法逆元,而 cfl/ 返回实参的乘法逆元。当传入 3 个或更多实参,cfl- 返回其第一个实参与其余实参之和的差,而 cfl/ 返回其第一个实参与其余实参之积的商。
(cfl+) => 0.0
(cfl*) => 1.0
(cfl- 5.0+1.0i) => -5.0-1.0i
(cfl/ 2.0+2.0i) => 0.25-0.25i
(cfl+ 1.0+2.2i -3.7+5.3i) => -2.7+7.5i
(cfl+ 1.0 -5.3) => -4.3
(cfl+ 1.0 2.0 -5.3i) => 3.0-5.3i
(cfl- 1.0+2.5i -3.7) => 4.7+2.5i
(cfl* 1.0+2.0i 3.0+4.0i) => -5.0+10.0i
(cfl/ -5.0+10.0i 1.0+2.0i 2.0) => 1.5+2.0i
procedure: (cfl-conjugate cflonum)
returns: cflonum 的共轭复数
libraries: (chezscheme)
当传入一个不精确的复数实参 a + bi 时,过程 cfl-conjugate 返回它的共轭复数 a + (-b)i.
参见 conjugate, 其为这个操作符的通用版本,对于一个复数的任何有效表现形式,返回其共轭复数。
(cfl-conjugate 3.0) => 3.0
(cfl-conjugate 3.0+4.0i) => 3.0-4.0i
(cfl-conjugate 1e-20-2e-30i) => 1e-20+2e-30i
procedure: (cfl-magnitude-squared cflonum)
returns: cflonum 的模的平方
libraries: (chezscheme)
当传入 1 个不精确的复数实参 a + bi, 过程 cfl-magnitude-squared 返回一个表示此实参的模的平方的 flonum, 即,a2 + b2.
参见 magnitude-squared, 其为此操作符的通用版本,对于 1 个复数的任何有效表示形式,返回它的模的平方。这两个操作都类似于过程 magnitude, 其返回它的复数实参的模,sqrt(a2 + b2).
(cfl-magnitude-squared 3.0) => 9.0
(cfl-magnitude-squared 3.0-4.0i) => 25.0
Section 8.5. 位和逻辑操作符
Chez Scheme 提供了一系列的逻辑操作符,以支持把精确整数 (fixnums 和 bignums) 作为位集合或位序列来处理。这些操作符包括 logand(逐位的逻辑与),logior(逐位的逻辑或),logxor(逐位的逻辑异或),lognot(逐位的逻辑非),logtest(测试多位),logbit?(测试单个位),logbit0(重置单个位),logbit1(设置单个位),以及 ash(算术移位)。这些操作符均把它的实参作为补码整数处理,不论这些实参的底层表示形式是什么。这种处理方法可被利用于表示无穷集合:a negative number represents an infinite number of one bits beyond the leftmost zero, and a nonnegative number represents an infinite number of zero bits beyond the leftmost one bit.
也提供了 fixnum 相应版本的逻辑操作符,比如 fxlogand, fxlogior, fxlogxor, fxlognot, fxlogtest, fxlogbit?, fxlogbit0, 以及 fxlogbit1. 还有三个用于移位的 fixnum 操作符: fxsll(逻辑左移位),fxsrl(逻辑右移位),fxsra(算术右移位)。逻辑和算术移位只在右移位上有差别。逻辑右移位在最左端填充 0,而算术右移位则复制符号位。
对任意精度的整数,逻辑移位没有意义,因为这些数没有必须移位的“最左端”。
procedure: (logand int …)
returns: 实参 int …的逻辑与
libraries: (chezscheme)
实参必须是精确的整数(fixnums 或 bignums),而且被作为补码整数处理,无论其底层的表示形式是什么。不传入实参时,logand 返回-1,即,所有位都设为 1.
(logand) => -1
(logand 15) => 15
(logand -1 -1) => -1
(logand -1 0) => 0
(logand 5 3) => 1
(logand #x173C8D95 7) => 5
(logand #x173C8D95 -8) => #x173C8D90
(logand #b1100 #b1111 #b1101) => #b1100
procedure: (logior int …)
procedure: (logor int …)
returns: 实参 int …的逻辑或
libraries: (chezscheme)
实参必须是精确的整数(fixnums 或 bignums),而且被作为补码整数处理,无论其底层的表示形式是什么。不传入实参时,logior 返回 0,即,所有位都被重置。
(logior) => 0
(logior 15) => 15
(logior -1 -1) => -1
(logior -1 0) => -1
(logior 5 3) => 7
(logior #b111000 #b101010) => #b111010
(logior #b1000 #b0100 #b0010) => #b1110
(apply logior '(1 2 4 8 16)) => 31
procedure: (logxor int …)
returns: 实参 int …的逻辑异或
libraries: (chezscheme)
实参必须是精确的整数(fixnums 或 bignums),而且被作为补码整数处理,无论其底层的表示形式是什么。不传入实参时,logxor 返回 0,即,所有位都被重置。
(logxor) => 0
(logxor 15) => 15
(logxor -1 -1) => 0
(logxor -1 0) => -1
(logxor 5 3) => 6
(logxor #b111000 #b101010) => #b010010
(logxor #b1100 #b0100 #b0110) => #b1110
procedure: (lognot int)
returns: int 的逻辑非
libraries: (chezscheme)
实参必须是精确的整数(fixnums 或 bignums),而且被作为补码整数处理,无论其底层的表示形式是什么。
(lognot -1) => 0
(lognot 0) => -1
(lognot 7) => -8
(lognot -8) => 7
procedure: (logbit? index int)
返回: 如果指定位被设置为 1,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
实参必须是精确的整数(fixnums 或 bignums),而且被作为补码整数处理,无论其底层的表示形式是什么。
如果在 int 的索引 index 处的位被设为 1,logbit? 返回#t, 否则返回#f. 索引基于 0,从最低位向最高位数。索引没有上限;对于非负的 int,在最高的设置位以上的位均被当作 0,而对负值,在最高的重置位以上的位都被当作 1.
logbit? 等价于
(lambda (k n) (not (zero? (logand n (ash 1 k)))))
但更加高效。
(logbit? 0 #b1110) => #f
(logbit? 1 #b1110) => #t
(logbit? 2 #b1110) => #t
(logbit? 3 #b1110) => #t
(logbit? 4 #b1110) => #f
(logbit? 100 #b1110) => #f
(logbit? 0 -6) => #f ; the two's complement of -6 is 1...1010
(logbit? 1 -6) => #t
(logbit? 2 -6) => #f
(logbit? 3 -6) => #t
(logbit? 100 -6) => #t
(logbit? (random 1000000) 0) => #f
(logbit? (random 1000000) -1) => #t
(logbit? 20000 (ash 1 20000)) => #t
procedure: (logtest int1 int2)
返回: 如果任何共同位被设为 1,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
实参必须是精确的整数(fixnums 或 bignums),而且被作为补码整数处理,无论其底层的表示形式是什么。
如果有任何位在两个实参中都被设为 1,则 logtest 返回#t. 如果两个实参中没有任何共同位被设为 1,则返回#f.
logtest 等价于
(lambda (n1 n2) (not (zero? (logand n1 n2))))
但更加高效。
(logtest #b10001 #b1110) => #f
(logtest #b10101 #b1110) => #t
(logtest #b111000 #b110111) => #t
(logtest #b101 -6) => #f ; the two's complement of -6 is 1...1010
(logtest #b1000 -6) => #t
(logtest 100 -6) => #t
(logtest (+ (random 1000000) 1) 0) => #f
(logtest (+ (random 1000000) 1) -1) => #t
(logtest (ash #b101 20000) (ash #b111 20000)) => #t
procedure: (logbit0 index int)
returns: 把 int 在索引 index 处的位清 0 后的结果
libraries: (chezscheme)
index 必须是一个非负的精确整数。int 必须是一个精确整数(fixnum 或 bignum),且被作为补码整数处理,无论它底层的表示形式是什么。
索引基于 0,从低位到高位计数。和 logbit?一样,索引没有上限。
logbit0 等价于
(lambda (i n) (logand (lognot (ash 1 i)) n))
但更加高效。
(logbit0 3 #b10101010) => #b10100010
(logbit0 4 #b10101010) => #b10101010
(logbit0 0 -1) => -2
procedure: (logbit1 index int)
returns: 把 int 在索引 index 处的位设为 1 后的结果
libraries: (chezscheme)
index 必须是一个非负的精确整数。int 必须是一个精确整数(fixnum 或 bignum),且被作为补码整数处理,无论它底层的表示形式是什么。
索引基于 0,从低位到高位计数。和 logbit?一样,索引没有上限。
logbit1 等价于
(lambda (i n) (logor (ash 1 i) n))
但更加高效。
(logbit1 3 #b10101010) => #b10101010
(logbit1 4 #b10101010) => #b10111010
(logbit1 4 0) => #b10000
(logbit1 0 -2) => -1
procedure: (ash int count)
returns: int 算术左移 count 位的结果
libraries: (chezscheme)
两个实参都必须是精确整数。第一个实参被作为补码整数处理,无论其底层的表示形式是什么。如果 count 是负数,则 int 右移 -count 位。
(ash 8 0) => 8
(ash 8 2) => 32
(ash 8 -2) => 2
(ash -1 2) => -4
(ash -1 -2) => -1
procedure: (fxlogand fixnum …)
returns: 实参 fixnum …的逻辑与
libraries: (chezscheme)
实参均被作为补码整数处理,无论其底层的表示形式是什么。不传入实参时,fxlogand 返回 -1, 即,所有位都设为 1.
(fxlogand) => -1
(fxlogand 15) => 15
(fxlogand -1 -1) => -1
(fxlogand -1 0) => 0
(fxlogand 5 3) => 1
(fxlogand #b111000 #b101010) => #b101000
(fxlogand #b1100 #b1111 #b1101) => #b1100
procedure: (fxlogior fixnum …)
procedure: (fxlogor fixnum …)
returns: 实参 fixnum …的逻辑或
libraries: (chezscheme)
实参均被作为补码整数处理,无论其底层的表示形式是什么。不传入实参时,fxlogior 返回 0, 即,所有位都被重置。
(fxlogior) => 0
(fxlogior 15) => 15
(fxlogior -1 -1) => -1
(fxlogior -1 0) => -1
(fxlogior #b111000 #b101010) => #b111010
(fxlogior #b1000 #b0100 #b0010) => #b1110
(apply fxlogior '(1 2 4 8 16)) => 31
procedure: (fxlogxor fixnum …)
returns: 实参 fixnum …的逻辑异或
libraries: (chezscheme)
The arguments are treated as two's complement integers, regardless of the underlying representation. With no arguments, fxlogxor returns 0, i.e., all bits reset. 实参均被作为补码整数处理,无论其底层的表示形式是什么。不传入实参时,fxlogxor 返回 0, 即,所有位都被重置。
(fxlogxor) => 0
(fxlogxor 15) => 15
(fxlogxor -1 -1) => 0
(fxlogxor -1 0) => -1
(fxlogxor 5 3) => 6
(fxlogxor #b111000 #b101010) => #b010010
(fxlogxor #b1100 #b0100 #b0110) => #b1110
procedure: (fxlognot fixnum)
returns: fixnum 的逻辑非
libraries: (chezscheme)
实参被作为补码整数处理,无论其底层的表示形式是什么。
(fxlognot -1) => 0
(fxlognot 0) => -1
(fxlognot 1) => -2
(fxlognot -2) => 1
procedure: (fxlogbit? index fixnum)
返回: 如果指定位是 1, 则为 #t
, 否则为 #f
.
libraries: (chezscheme)
index 必须是非负 fixnum. fixnum 被作为补码整数处理,无论其底层的表示形式是什么。
如果 fixnum 在索引 index 处的位被设为 1,则 fxlogbit? 返回 #t, 否则返回#f. 索引基于 0,从最低位向最高位计数。索引只受限 fixnum 的范围;对于非负的 int,在最高的设置位以上的位均被当作 0,而对负值,在最高的重置位以上的位都被当作 1.
(fxlogbit? 0 #b1110) => #f
(fxlogbit? 1 #b1110) => #t
(fxlogbit? 2 #b1110) => #t
(fxlogbit? 3 #b1110) => #t
(fxlogbit? 4 #b1110) => #f
(fxlogbit? 100 #b1110) => #f
(fxlogbit? 0 -6) => #f ; the two's complement of -6 is 1...1010
(fxlogbit? 1 -6) => #t
(fxlogbit? 2 -6) => #f
(fxlogbit? 3 -6) => #t
(fxlogbit? 100 -6) => #t
(fxlogbit? (random 1000000) 0) => #f
(fxlogbit? (random 1000000) -1) => #t
procedure: (fxlogtest fixnum1 fixnum2)
返回: 如果任何共同位为 1,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
实参均被作为补码整数处理,无论其底层的表示形式是什么。
如果有任何位在两个实参中均为 1,则 fxlogtest 返回 #t. 如果两个实参中没有任何共同位被设为 1,则返回 #f.
(fxlogtest #b10001 #b1110) => #f
(fxlogtest #b10101 #b1110) => #t
(fxlogtest #b111000 #b110111) => #t
(fxlogtest #b101 -6) => #f ; the two's complement of -6 is 1...1010
(fxlogtest #b1000 -6) => #t
(fxlogtest 100 -6) => #t
(fxlogtest (+ (random 1000000) 1) 0) => #f
(fxlogtest (+ (random 1000000) 1) -1) => #t
procedure: (fxlogbit0 index fixnum)
returns: fixnum 在索引 index 处的位被清零后的结果
libraries: (chezscheme)
fixnum 被作为补码整数处理,无论其底层的表示形式是什么。index 必须非负,且小于一个 fixnum 中的位数(不包括符号位),即,小于 (integer-length (most-positive-fixnum)).索引基于 0,从最低位向最高位计数。
fxlogbit0 等价于
(lambda (i n) (fxlogand (fxlognot (fxsll 1 i)) n))
但更加高效。
(fxlogbit0 3 #b10101010) => #b10100010
(fxlogbit0 4 #b10101010) => #b10101010
(fxlogbit0 0 -1) => -2
procedure: (fxlogbit1 index fixnum)
returns: fixnum 在索引 index 处的位被设为 1 后的结果
libraries: (chezscheme)
fixnum 被作为补码整数处理,无论其底层的表示形式是什么。index 必须非负,且小于一个 fixnum 中的位数(不包括符号位),即,小于 (integer-length (most-positive-fixnum)).索引基于 0,从最低位向最高位计数。
fxlogbit1 等价于
(lambda (i n) (fxlogor (fxsll 1 i) n))
但更加高效。
(fxlogbit1 3 #b10101010) => #b10101010
(fxlogbit1 4 #b10101010) => #b10111010
(fxlogbit1 4 0) => #b10000
(fxlogbit1 0 -2) => -1
procedure: (fxsll fixnum count)
returns: fixnum 左移 count 位
libraries: (chezscheme)
fixnum 被作为补码整数处理,无论其底层的表示形式是什么。count 必须非负,且不大于一个 fixnum 中的位数,即,(+ (integer-length (most-positive-fixnum)) 1). 如果结果不能表示为 fixnum,则会抛出一个条件类型的 &implementation-restriction 异常。
(fxsll 1 2) => 4
(fxsll -1 2) => -4
procedure: (fxsrl fixnum count)
returns: fixnum 逻辑右移 count 位
libraries: (chezscheme)
fixnum 被作为补码整数处理,无论其底层的表示形式是什么。count 必须非负,且不大于一个 fixnum 中的位数,即,(+ (integer-length (most-positive-fixnum)) 1).
(fxsrl 4 2) => 1
(= (fxsrl -1 1) (most-positive-fixnum)) => #t
procedure: (fxsra fixnum count)
returns: fixnum 算术右移 count 位
libraries: (chezscheme)
fixnum 被作为补码整数处理,无论其底层的表示形式是什么。count 必须非负,且不大于一个 fixnum 中的位数,即,(+ (integer-length (most-positive-fixnum)) 1).
(fxsra 64 3) => 8
(fxsra -1 1) => -1
(fxsra -64 3) => -8
Section 8.6. 随机数生成
procedure: (random real)
returns: 小于 real 的一个非负伪随机数
libraries: (chezscheme)
real 必须是正整数,或正的不精确实数。
(random 1) => 0
(random 1029384535235) => 1029384535001, every now and then
(random 1.0) => 0.5, every now and then
thread parameter: random-seed
libraries: (chezscheme)
随机数生成器支持通过参数对象 random-seed 获取和修改当前的随机数种子。
不带实参调用时,random-seed 返回当前的随机数种子。当带 1 个实参调用时,实参必须是 1 至 232 -1 之间的非负精确整数,而 random-seed 把当前的随机数种子设为此实参的值。
(let ([s (random-seed)])
(let ([r1 (random 1.0)])
(random-seed s)
(eqv? (random 1.0) r1))) => #t
Section 8.7. 其它各类数字操作
procedure: (= num1 num2 num3 …)
procedure: (< real1 real2 real3 …)
procedure: (> real1 real2 real3 …)
procedure: (<= real1 real2 real3 …)
procedure: (>= real1 real2 real3 …)
返回: 如果关系成立,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
这些谓词和 R6RS 中的对应版本一样,只是它们被扩展为可接受 1 个以上参数,而非 2 个以上参数。当传入 1 个参数时,这些谓词均返回 #t.
(> 3/4) => #t
(< 3/4) => #t
(= 3/4) => #t
procedure: (1+ num)
procedure: (add1 num)
procedure: (1- num)
procedure: (-1+ num)
procedure: (sub1 num)
returns: num 加 1 或 num 减 1
libraries: (chezscheme)
1+ 和 add1 等价于 (lambda (x) (+ x 1)); 1-, -1+, 和 sub1 等价于 (lambda (x) (- x 1)).
(define plus
; x should be a nonnegative integer
(lambda (x y)
(if (zero? x)
y
(plus (1- x) (1+ y)))))
(plus 7 8) => 15
(define double
; x should be a nonnegative integer
(lambda (x)
(if (zero? x)
0
(add1 (add1 (double (sub1 x)))))))
(double 7) => 14
procedure: (expt-mod int1 int2 int3)
returns: int1 的 int2 次方,再对 int3 取模
libraries: (chezscheme)
int1, int2 和 int3 必须是非负整数。expt-mod 采用的计算方式使得中间结果永远不会比 int3 大太多。这意味着,当 int2 很大时,expt-mod 要比等价过程 (lambda (x y z) (modulo (expt x y) z)) 更加高效。
(expt-mod 2 4 3) => 1
(expt-mod 2 76543 76543) => 2
procedure: (isqrt n)
returns: n 的整数平方根
libraries: (chezscheme)
n 必须是非负整数。The integer square root of n is defined to be =>.TODO
(isqrt 0) => 0
(isqrt 16) => 4
(isqrt 16.0) => 4.0
(isqrt 20) => 4
(isqrt 20.0) => 4.0
(isqrt (* 2 (expt 10 20))) => 14142135623
procedure: (integer-length n)
returns: 参见下文
libraries: (chezscheme)
过程 integer-length 返回 n 的最小补码表示形式的位数长度,并假设负数前面有一个为 1 的符号位。对于 0,integer-length 返回 0.
(integer-length 0) => 0
(integer-length 1) => 1
(integer-length 2) => 2
(integer-length 3) => 2
(integer-length 4) => 3
(integer-length #b10000000) => 8
(integer-length #b11111111) => 8
(integer-length -1) => 0
(integer-length -2) => 1
(integer-length -3) => 2
(integer-length -4) => 2
procedure: (nonpositive? real)
返回: 如果 real 不大于 0,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
nonpositive? 等价于 (lambda (x) (<= x 0)).
(nonpositive? 128) => #f
(nonpositive? 0.0) => #t
(nonpositive? 1.8e-15) => #f
(nonpositive? -2/3) => #t
procedure: (nonnegative? real)
返回: 如果 real 不小于 0,则为 #t
, 否则为 #f
.
libraries: (chezscheme)
nonnegative? 等价于 (lambda (x) (>= x 0)).
(nonnegative? -65) => #f
(nonnegative? 0) => #t
(nonnegative? -0.0121) => #f
(nonnegative? 15/16) => #t
procedure: (conjugate num)
returns: num 的共轭复数
libraries: (chezscheme)
当过程 conjugate 传入复数实参 a + bi 时,返回它的共轭复数 a + (-b)i.
(conjugate 3.0+4.0i) => 3.0-4.0i
(conjugate 1e-20-2e-30i) => 1e-20+2e-30i
(conjugate 3) => 3
procedure: (magnitude-squared num)
returns: num 的模的平方
libraries: (chezscheme)
对过程 magnitude-squared 传入复数实参 a + bi 时,返回它的模的平方,即,a2 + b2.
(magnitude-squared 3.0-4.0i) => 25.0
(magnitude-squared 3.0) => 9.0
procedure: (sinh num)
procedure: (cosh num)
procedure: (tanh num)
returns: num 的 hyperbolic sine, cosine, 或 tangent
libraries: (chezscheme)
(sinh 0.0) => 0.0
(cosh 0.0) => 1.0
(tanh -0.0) => -0.0
procedure: (asinh num)
procedure: (acosh num)
procedure: (atanh num)
returns: num 的 hyperbolic arc sine, arc cosine, 或 arc tangent
libraries: (chezscheme)
(acosh 0.0) => 0.0+1.5707963267948966i
(acosh 1.0) => 0.0
(atanh -1.0) => -inf.0
procedure: (string->number string)
procedure: (string->number string radix)
returns: string 所表示的数字,或 #f
libraries: (chezscheme)
这个过程和 R6RS 版本一样,除了基数可以是 2 至 36(两端包含)之间的任意精确整数。R6RS 版本要求基数属于集合 {2,8,10,16}.
(string->number "211012" 3) => 559
(string->number "tobeornottobe" 36) => 140613689159812836698
procedure: (number->string num)
procedure: (number->string num radix)
procedure: (number->string num radix precision)
returns: 作为字符串的一种 num 的外部表示形式 an external representation of num as a string
libraries: (chezscheme)
这个过程和 R6RS 版本一样,除了基数可以是 2 至 36(两端包含)之间的任意精确整数。R6RS 版本要求基数属于集合 {2,8,10,16}.
(number->string 10000 4) => "2130100"
(number->string 10000 27) => "DJA"
Chez Scheme Version 9 User's Guide Copyright © 2018 Cisco Systems, Inc. Licensed under the Apache License Version 2.0 (full copyright notice.). Revised January 2019 for Chez Scheme Version 9.5.1 about this book