浮点错误是确定的吗?

Are floating point errors deterministic?

本文关键字:错误      更新时间:2023-10-16

浮点数的一个大问题是它们中的一些不能精确地用二进制表示。这可能会让他们难以相处。然而,我好奇的是,浮点数中细微或不那么细微的错误是否具有确定性。有人能预测一下吗?下面是一个可以利用浮点错误的随机数生成器的示例:

#include <cmath>
float constant = M_PI;
float generate()
{
    static float state = 1;
    state = state * constant;
    return state;
}

必须知道实现、硬件、编译器设置等等,这使得很难预测结果是什么。还是我的想法有问题?

浮点数"错误"是确定性的。给定操作的输入值和输出值之间存在1:1的映射。您的示例每次都会产生相同的输出序列。

也就是说,可能有一个或十个浮点实现会产生不同的序列,但这不是你可以考虑的"随机"(即熵的来源)。

每个浮点表示定义了浮点变量的组成(哪一部分是尾数,哪一部分是指数,哪一部分是符号,等等)和每个操作的行为。

因此,在您可能选择的任何实现中,如果您知道其操作数(或操作数),则可以预测每个浮点操作的结果。该特性是确定性的定义。

所以,是的,浮点运算是确定性的。

不同的实现(编译器、主机系统等)支持不同的浮点表示。所以在不同的实现之间会有不同的结果。但是,如果您知道浮点变量是如何表示的,以及操作是如何工作的,那么仍然可以预测任何浮点操作的结果。

并非每个人都足够了解浮点类型及其操作,但这并不意味着它们不确定。也不是每个人都能描述复杂算法中的全部操作。这些知识很容易获得,而且只要付出足够的努力,就能很好地理解,因此在执行操作之前,可以可靠地预测所有操作对所有可能操作数的影响。

有一些浮点数的错误实现,它们不符合它们自己的文档。例如,查找pentium FDIV错误——一些早期的pentium cpu不正确地实现了浮点除法。一旦理解了这些操作的实际作用,即使这些操作也被证明是确定的。