测试双数的浮点算术实现有哪些好的策略?

计算科学 浮点 测试
2021-11-23 23:30:53

对于 IEEE,单一表示是 1 位符号、8 位指数和 23 位尾数。这意味着在每个指数值处,您可以测试所有 2^23-1(大约 900 万例)二进制表示(给或取)的可能组合。然后对所有的指数值(255个值)做,基本可以覆盖IEEE代表的所有浮点数。

但是,对于双精度,这种方法实际上并不可行。使用 52 位尾数,在每个指数值处,您需要测试 2^52-1 个二进制组合(大约为 400 亿,~E15)。

这似乎表明您需要一些随机化方案来测试您的算术实现是否具有高概率。但是我们知道使用哪种方案吗?考虑浮点数的分布方式(即更多地围绕某个值/零并置)是否也有益?

4个回答

您应该测试转换点。

浮点数有几个不同的“范围”:

  • 标准/普通算术
  • 次正规算术
  • 无限算术
  • NaN 算术
  • 零算术

例如,如果我将任何正常数添加到无限数,我需要得到一个无限数。如果我添加两个足够大的次正规,我应该得到一个正常的数字。对 NaN 进行的任何数学运算都会产生 NaN。添加两个大法线可能会给我一个 Inf。

所以我的测试策略是:

  • 随机检查一些数学实例,其中答案保留在一个类中(请注意,影响指数的操作可以与仅影响尾数的变化区分开来)。如果 1+2=3,那么我可能也得到了正确的 2+3=5。
  • 花更多的时间/精力在班级边界检查数学,因为这些代表特殊情况。

我可能会编写一些单元测试来探索我很好理解的特定案例,然后使用基于属性的测试来更彻底。这特别适用于零、inf 和 NaN 之类的东西。

最后,我会测量代码覆盖率以确保测试套件能够覆盖整个库。

预先存在的测试套件包括:

  • 卡汉的偏执狂
  • Schryer 的“A Test of a Computer's Floating-Point Arithmetic Unit”(我还没有找到源代码)

一个非常经典的方法是测试身份。例如,选择一个,使用泰勒级数为三角函数计算,并检查结果是否等于 1 到舍入误差内。这样做的好处是您不必与您希望是正确的其他人的浮点实现进行比较。类似的例子是 ,或者使用几何级数计算 ,然后使用除法和减法计算xsin2x+cos2xtan(tan1x)y=1/(1x)11/y

在线搜索显示了各种支持双精度(64 位 IEEE 754)的浮点测试套件,这些套件比随机测试更全面。我自己没有测试过这些。例子:

一种被低估的策略是仅使用大量随机数进行测试。具体来说,我发现将随机 64 位整数重新解释为浮点数会产生非常好的分布,因为它会生成大量具有大小指数的数字。对有符号零、NaN、Infs 和次正规等事物的目标测试绝对是必要的,但不应低估仅测试 2^32 个随机值。