我在教科书上做了一些家庭作业问题,对于某些算术运算有浮点舍入/精度问题。
如果我从这样的int中输出双打:
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但是没有足够的信息来解释这是怎么发生的,或者它是否会随着其他的分工而变化。
答案 0 :(得分:1)
假设int
最多为32位,double
遵循IEEE-754。 double
可以精确地存储整数值2 53 。
在补充的情况下:
(dx + dy) + dz == dx + (dy + dz)
==
的两边都有精确的值,因此它是关联的。
在乘法的情况下:
(dx * dy) * dz == dx * (dy * dz)
该值可能超过2 53 ,因此不能保证它们相等。
答案 1 :(得分:1)
你应该理解浮点数通常在内部表示为符号位,固定点尾数(52位,IEEE 64-bit doubles隐含的前导码)和二进制指数(IEEE双打11位) )。您可以将指数视为给定值的数学单位的“量子”。
如果总和全部适合尾数而指数不超过2 0 == 1,则加法应该是关联的。如果random()
产生32位整数,则总和如此如果(dx + dy) + dz
适合,则添加将是关联的。
在乘法的情况下,很容易看出2个32位数的乘积可能超过53位,所以指数可能需要超过1才能包含尾数以包含结果的大小,所以结合失败。
对于除法,在dx / dx
的特定情况下,编译器可以用常量1.0替换表达式(可能在零检查之后)。