我正在做一些课本上的作业问题,并且对某些算术运算的浮点舍入/精度有一些问题。
如果我像这样从整数中铸造双打:
int x = random();
double dx = (double) x;
假设变量y、z、dy和dz遵循相同的格式。
然后是这样的操作:
(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 替换表达式(可能在零检查之后)。