3. 数字(Numbers)
本章描绘Scheme的数字模型。区别如下对象的不同是重要的:数学上的数字,尝试去建模这些数字的Scheme对象,用于实现这些数字的机器表示和用于书写数字的符号。在本报告中,术语数字表示数学上的数字,术语数字对象(number object)表示代表一个数字的Scheme对象。本报告使用类型复数(complex),实数(real),有理数(rational)和整数(integer)同时表示数学上的数字和数字对象。定长数(fixnum)和浮点数(flonum)类型表示这些数字对象的特殊子集,由通常的机器表示决定,这些会在下面说明。
3.1. 数值塔(Numeracal tower)
数字可以被组织在一个子集的塔中,在这个塔中,每一层是上一层的子集:
number
complex
real
rational
integer
比如,5是一个整数。因此,5也是一个有理数,实数和复数。为5建模的数字对象也一样。
数字对象也被组织为一个对应的子类型的塔,这些类型被谓词(predicates)number?, complex?, real?, rational?和integer?定义;见11.7.4.1节。整形数字对象也被叫做整数对象(integer objects)。
包含一个数字的子集和它在计算机中的表示是没有简单的关系的。比如,整数5可以有多个表示。Scheme的数值操作将数字对象当作抽象数据对待,尽可能和它们的表示相独立。尽管Scheme的实现可以使用不同的数字表示方法,但这些对于偶尔编些简单程序的程序员来说不应该是明显可见的。
3.2. 精确性(Exactness)
区分一个已知的精确等于一个数字的数字对象和那些在计算过程中有近似和误差的数字对象是有用的。比如,数据结构的索引操作可能需要精确地了解索引,符号代数系统中的多项式系数也应如此。另一方面,测量的结果在本质上就是不精确的,无理数可以被近似地表示为有理数,这也是不精确的近似。为了在需要精确数的地方使用非精确数,Scheme显式区分精确(exact)和非精确(inexact)数。这种区分和类型的划分是正交的(orthogonal)关系。
如果一个数值被写作精确的常量,或是完全通过精确运算从精确数得出,它就是精确的。一个精确的数字对象明显地与一个数学上的数字相一致。
同样地,如果一个数值被写作非精确的常量,或者是由非精确的成分得出的,或者是由非精确的运算得出的,它就是非精确的。也就是说,非精确性是数值的一种可传染的特性。
精确算术在下面的场景是可靠的:一个精确数对象被传递到11.7.1节描述的任意一个算术过程,并返回一个精确数对象,这个结果是数学上正确的。然而在涉及到非精确数的计算的时候,这通常是不正确的,这时因为像浮点算法的近似方法可能被使用,但是,让结果尽可能接近数学上的理想结果是每个实现的职责。
3.3. 定长数和浮点数
一个定长数是一个精确的整数对象,这个整数对象在精确的整数对象的一个特定的实现相关的子范围(subrange)。(库的第11.2小节描绘了一个计算定长数的库。)同样地,每个实现应当指定一个非精确实数对象的子集作为浮点数,并将特定的外部表示转换成浮点数。(库的第11.3小节描绘了一个计算浮点数的库。)注意,这并不意味着实现必须使用浮点表示。
3.4. 实现要求
Scheme的实现必须支持3.1节给出的子类型的整个塔的数字对象。此外,实现必须支持几乎无限(Practically unlimited)大小和精度的精确整数对象和精确有理数对象,并实现特定的过程(在11.7.1节列出),当给它们精确参数的时候这些过程总是返回精确结果。(“几乎无限”意味着这些数字的大小和精度应当仅受可用内存大小的限制。)
实现可以只支持任意类型非精确数字对象的一个有限的值域(range),但需要遵从本节的要求。比如,一个实现可以限制非精确实数对象的值域(且因此限制非精确整数和有理数对象的值域)在浮点格式的动态值域内。此外,在使用这种值域限制的实现中,非精确整数对象和有理数之间的差异很可能会很大。
一个实现可以为非精确数字使用浮点或其它近似表示方法。本报告推荐但不要求实现遵从IEEE的浮点格式标准,使用其他表示方法的实现应当在精度上达到或超过这些浮点标准15。
特别地,使用浮点数表示法的Scheme实现必须遵循以下规则:浮点数结果的表示精度必须达到或超过参与该运算的任意非精确参数的表示精度。只要有可能,像sqrt这样潜在的非精确操作当传递一个精确的参数时,应该返回一个精确的结果(比如精确数4的平方根应当是精确的2)。可是,这不是必须的。另一方面,如果参数是精确数的运算会产生非精确的结果(如通过sqrt),且该结果被表示为浮点数,那么就必须使用当前可用的精度最高的浮点数格式;不过,如果该结果是用其他形式表示的,那么该表示方法在精度上就必须达到或超过当前可用的精度最高的浮点数格式。
避免使用量级或有效数字大到实现无法表示的非精确数是程序员的责任。
3.5. 无穷大(Infinities)和非数(NaNs)
一些Scheme实现,尤其是那些遵从IEEE浮点格式标准的实现区别叫做正无穷大,负无穷大和非数的特殊数字对象。
正无穷大被认为是一个非精确的实数(但不是有理数)对象,它表示大于所以有理数对象表示的数字的一个模糊的数字。负无穷大被认为是一个非精确的实数(但不是有理数)对象,它表示小于所以有理数对象表示的数字的一个模糊的数字。
一个非数被认为是一个非精确数(但不是一个实数)对象,它是如此不确定以至于它可以表示任何数,包括正负无穷大,且甚至可能大于正无穷大或小于负无穷大。
3.6. 可区别的-0.0
一些Scheme实现,尤其是那些遵从IEEE浮点格式标准的实现区别数字对象0.0和-0.0。也就是说,正的和负的非精确的零。本报告有时会指定在这些数字对象上的特定算术操作的行为。这些说明会被写作“如果-0.0的话是不一样的”或“实现区分-0.0”。