Scheme 方案-“;“不精确”;R5RS数字塔中的概念

Scheme 方案-“;“不精确”;R5RS数字塔中的概念,scheme,r5rs,inexact-arithmetic,Scheme,R5rs,Inexact Arithmetic,在思考如何实现方案R5RS时,我对以下R5RS摘录感到困惑(第22-23页): (余数-13-4)==>-1 (余数-13-4.0)==>-1.0;不精确 (lcm 32-36)=>288 (lcm 32.0-36)=>288.0;不精确 (分母(/64))==>2 (分母(精确->不精确(/64))==>2.0 我们是否应该理解,即使-4.0、32.0和(精确->不精确(/64))是不精确的,实现也应该“记住”它们的精确等价物(-4、32和3/2),以便进行整数除法、素因子分解等 否则,实施如

在思考如何实现方案R5RS时,我对以下R5RS摘录感到困惑(第22-23页):

(余数-13-4)==>-1
(余数-13-4.0)==>-1.0;不精确

(lcm 32-36)=>288
(lcm 32.0-36)=>288.0;不精确

(分母(/64))==>2
(分母(精确->不精确(/64))==>2.0

我们是否应该理解,即使-4.0、32.0和(精确->不精确(/64))是不精确的,实现也应该“记住”它们的精确等价物(-4、32和3/2),以便进行整数除法、素因子分解等

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

提前感谢您对本主题的介绍!:)


Nicolas

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

> (+ -1.0 2)
=> 1.0
在内部,解释器可以将
2
升级为
float
,并调用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));
 }
实际上,口译员将上述加入方案视为:

> (+ -1.0 2.0)
=> 1.0   
它不必“记住”原始论点的正确性。在计算过程中,它可以临时(内部)将数字转换为精确,如果任何参数不精确,则将结果标记为不精确

示例:

(denominator 1/10)  ; 10
(denominator 0.1)   ; 3.602879701896397e+16
(后一个结果取决于实现。我引用的数字来自运行在amd64上的Racket 5.0.2。您将从其他实现中获得不同的结果。)

对于潜伏者和档案:不寻常的结果是因为大多数实现使用IEEE 754来表示不精确的数字,而不精确的数字(是二进制浮点格式)不能以全精度表示0.1(只有十进制浮点格式可以)


事实上,如果您使用
(不精确->精确0.1)
,则不会得到
1/10
,除非您的实现使用十进制浮点。

谢谢您的回答。我完全同意你的看法。但是,如果您再次查看以粗体显示的R5R摘录,解释器似乎能够对“浮点”不精确数字执行“整数”操作,例如(分母(/1.0 3.0))。这就是让我困惑的地方。@Nicolas_75:
(分母(/1.0 3.0))
不必返回3.0。在大多数实现中,事实上并不是这样。(我在我的电脑Racket 5.0.2上得到的结果是18014398509481984.0。如果这对你没有意义,请参阅我的帖子。)