Chapter 8. 数字操作

本章介绍了 Chez Scheme 对数字对象上的标准操作集的扩展。参见"The Scheme Programming Language, 第 4 版", 第 6 章,或 R6RS 中对数字对象上标准操作的介绍。

Chez Scheme 支持全部 Scheme 数字类型,包括精确和不精确整数,有理数,实数,及复数。并使用了一系列表示形式支持这些数据类型:

Fixnums 在 fixnum 范围内表示精确整数(参见 most-negative-fixnummost-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 的数字用字母 az 指定(大写小写均可)。例如, ~#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-fixnumleast-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

results matching ""

    No results matching ""