C语言 浮点加法/乘法/除法



我正在做一些课本上的作业问题,并且对某些算术运算的浮点舍入/精度有一些问题。

如果我像这样从整数中铸造双打:

int x = random();
double dx = (double) x; 

假设变量yzdydz遵循相同的格式。

然后是这样的操作:

(dx + dy) + dz == dx + (dy + dz)
(dx * dy) * dz == dx * (dy * dz)

具有关联性?我知道如果我们有分数表示,那么它就不会是关联的,因为根据操作数相互加/乘法,四舍五入会丢失一些精度。但是,由于这些是从整数中铸造的,我觉得精度不会成为问题,并且可以关联吗?

最后,我使用的教科书根本没有解释FP除法,所以我想知道这个说法是否正确,或者至少只是浮点除法的一般工作原理:

dx / dx == dz / dz

我在网上查了一下,我读到了一些地方,比如像3/3这样的操作可以产生.999...9,但没有足够的信息来解释这是如何发生的,或者它是否会与其他部门操作不同。

假设int最多是32位,并且double遵循IEEE-754。double最多可以精确存储253的整数值。


在添加的情况下:

(dx + dy) + dz == dx + (dy + dz)

==的两边都有其精确的值,因此它是关联的。


在乘法的情况下:

(dx * dy) * dz == dx * (dy * dz)

该值可能超过 253,因此不能保证它们相等。

您应该了解,浮点数通常在内部表示为符号位、定点尾数(52 位,IEEE 64 位双精度为隐含前导)和二进制指数(IEEE 双精度为 11 位)。您可以将指数视为给定值的数学单位的"量子"。

如果总和都适合尾数,而指数不超过 20== 1,则加法应该是关联的。如果random()生成 32 位整数,则(dx + dy) + dz等总和将适合,并且加法将是关联的。

在乘法的情况下,很容易看出 2 个 32 位数字的乘积可能远远超过 53 位,因此指数可能需要高于 1 才能使尾数包含结果的大小,因此关联性失败。

对于除法,在dx / dx的特定情况下,编译器可以用常量 1.0 替换表达式(可能在零检查之后)。

最新更新