5

如果有效数字的最低有效位被设置为随机值,对浮点数学可能产生什么影响?

解释:

PicoLisp语言使用一种结构分配所有值,即单元格,它由两个“机器字”组成。在 32 位系统上,这意味着一个单元是由两个 32 位指针或整数组成的八字节结构。单元格与它们的大小对齐,这意味着至少一个字的最低三位可以自由地用作类型和 GC 标记数据。

PicoLisp 非常简约。该语言缺乏的(许多)事情之一是对浮点数的任何支持,而不是完全依赖于文档所谓的“缩放定点”表示。我认为尝试添加浮点支持会很有趣。

在 32 位系统上,一个 64 位浮点数将整齐地放入一个单元格中,这意味着分配系统可以几乎相同,除了一个小问题:所有 64 位将被双精度使用。但是 GC 期望使用位 0 作为 GC 标记位。天真地进行,在每个收集周期之后,位 0 将被设置为零,而不管实际存储在双精度中的值是什么。

(这是假设大小和字节顺序都正确排列。为此假设他们这样做;如果他们不这样做,那么整个问题是完全不相关的,并且必须使用不同的策略。)

那么:对于使用硬件浮点运算的通用数学来说,这有多大的问题?

如果它所做的只是稍微降低 double 的精度,那么我认为这实际上不是问题:只要有文件证明解释器中的浮点数学不如用户期望的那么精确,他们应该如果他们需要严格准确的行为,则回退到固定点或库或其他东西。我对它的直观理解是应该是这种情况,因为它是最低有效位(当您转换为字符串时甚至不会出现......?)。

另一方面,浮点是,呃,巫术。这种比特摆弄真的会严重影响数学的有用性或产生任何一致结果的能力吗?

(我已经考虑了分配器的其他几种实现可能性。我特别感兴趣的是这个策略是否非常愚蠢,因为它最简单而且我很懒惰。)

4

3 回答 3

2

只要外部代码总是看到该值,就好像低位已被四舍五入,并且您通过将尾数四舍五入到最接近的偶数值来做到这一点,对于正常计算就可以了。

也就是说,对于以以下结尾的尾数:

00: 没做什么

10: 没做什么

01: 尾数减 1

11:尾数加 1(溢出时,您需要增加指数并清除尾数)

如果你的四舍五入不一致,只是去掉低位,你会在计算中引入一个非常轻微的向下偏差。向偶数四舍五入是 IEEE 抵消这种向下偏差的方式。

小心 +/- 无穷大,因为设置低位会将它们变成 NAN,使用起来非常脆弱(突然你所有的比较操作都开始失败)。

于 2013-05-09T00:25:06.203 回答
2

StilesCrisis 提出的方案会导致双舍入,这通常被认为是一件坏事

我想建议的另一种选择:

显示和计算每个 PicoLisp 浮点数,就好像它比它大2 512倍。这意味着双加减法几乎保持不变,乘法和除法需要一次廉价的调整,而其他操作(库调用)需要两次调整,一次之前和一次之后。

每次操作后,检查溢出(现在发生的频率更高,每次偏差结果高于 1.0 时)。

如果你这样做,而不是借用有效位的最低有效位,你实际上是在借用指数的最高有效位。这需要一些位改组来加载和存储浮点数,但这将更容易向使用系统的程序员解释,并且为类似 IEEE 754 的属性设计的算法将继续工作(除非它们现在溢出)。


代码可能看起来像这个经过轻微测试的实现。另一个上下文中的类似实现是这篇文的对象,它提供了更多解释。

void smalldouble_to_cell(void*p, double d)
{
  union u u;
  u.d = d;
  unsigned long long rest = u.u & 0x7fffffffffffffff;
  unsigned long long packed;
  if (rest > 0x7ff0000000000000)
    /* NaN */
    packed = u.u & 0xfffffffffffffffe;
  else 
    {
      unsigned long long sign = u.u & 0x8000000000000000;
      if (rest >= 0x3ff0000000000000)
    rest = 0x3ff0000000000000;
      packed = sign | (rest << 1);
    }
  memcpy(p, &packed, 8);
}

void double_to_cell(void *p, double d)
{
  smalldouble_to_cell(p, ldexp(d, -512));
}
于 2013-05-09T06:03:53.050 回答
1

有效数字的最低有效位的变化通常会产生您认为的效果 - 它会改变数字的最低有效记录位。

但是,您会遇到一些特殊情况的问题。

[根据 Eric Postpischil 对我之前的文本的准确批评进行编辑:调整零表示只会导致非常小的非正规数]

你会看到类似正负无穷编码的相反问题。Infinity 使用最大可能的指数和零有效数进行编码。如果有效数字被修改,则无穷大将变为 NaN。

于 2013-05-09T00:26:31.993 回答