2

在思考实现方案 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 和 (exact->inexact (/6 4)) 不精确,实现也应“记住”它们的精确等价物(-4、32 和 3/2),以便继续整数除法,素因子分解等?

否则,实施如何成功地给出上述答案?

提前感谢您对这个主题的任何启发!:)

尼古拉斯

4

2 回答 2

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,除非你的实现使用十进制浮点数。

于 2011-02-10T13:56:53.437 回答
1

实现不需要记住精确的等价物,因为根据 R5RS,如果操作涉及不精确的操作数,则可以产生不精确的结果。例如:

> (+ -1.0 2)
=> 1.0

在内部,解释器可以升级2为 afloat并调用浮点数的加法操作,无需记住任何内容:

/* 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   
于 2011-02-10T10:58:33.997 回答