在考虑实施Scheme R5RS的方法时,我对以下R5RS的摘录(第22-23页)感到困惑:
(余数-13 -4)==> -1
(余数-13 -4.0)==> -1.0;不精确(lcm 32 -36)==> 288个
(lcm 32.0 -36)==> 288.0;不精确(分母(/ 6 4))==> 2
(分母(确切 - >不精确(/ 6 4)))==> 2.0
我们应该理解,即使-4.0,32.0和(确切 - >不精确(/ 6 4))不精确,实现也应该“记住”它们的确切等价(-4,32和3/2)为了进行整数除法,素数因子分解等?
否则,实施如何成功地提供上述答案?
提前感谢您可以投入任何光线! :)
尼古拉斯
答案 0 :(得分:1)
实现不需要记住确切的等价物,因为根据R5RS,如果操作涉及不精确的操作数,则可以产生不精确的结果。 E.g:
> (+ -1.0 2)
=> 1.0
在内部,解释器可以将2
升级为float
并调用浮点数的加法运算,无需记住任何内容:
/* Assuming that the interpreter implements primitive operations in C. */
SchemeObject* addInts(SchemeObject* a, SchemeObject* b)
{
if (a->type == FLOAT || b->type == FLOAT)
{
cast_int_value_to_float (a);
cast_int_value_to_float (b);
return addFloats (a, b);
}
return make_new_int_object (get_int_value (a) + get_int_value (b));
}
实际上,Scheme中的上述添加内容由解释器处理为:
> (+ -1.0 2.0)
=> 1.0
答案 1 :(得分:1)
它不必“记住”参数的原始精确性。它可以在计算过程中暂时(内部)将数字转换为精确数字,如果任何参数不准确,则将结果标记为不精确。
示例:
(denominator 1/10) ; 10
(denominator 0.1) ; 3.602879701896397e+16
(后者的结果与实现有关。我引用的数字来自在amd64上运行的Racket 5.0.2。你会得到与其他实现不同的结果。)
对于潜伏者和档案馆:看起来很不寻常的结果是因为大多数实现都使用IEEE 754来表示不精确的数字,它们(是一个二进制浮点格式)不能用完全精度表示0.1(只有十进制浮点格式才能)
事实上,如果您使用(inexact->exact 0.1)
,除非您的实现使用十进制浮点,否则您将无法获得1/10
。