浮点加法/乘法/除法

Floating Point Addition / Multiplication / Division

提问人:cheng 提问时间:5/7/2015 更新时间:5/7/2015 访问量:869

问:

我正在做教科书中的一些家庭作业,并且对某些算术运算的浮点舍入/精度有一些问题。

如果我像这样从 int 中转换双打:

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

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

然后会像这样操作:

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

有关联性吗?我知道,如果我们有分数表示,那么它就不会是关联的,因为根据哪些操作数相互相加/相乘,舍入会损失一些精度。但是,由于这些是从 ints 转换的,我觉得精度不会成为问题,而且这些可以关联吗?

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

dx / dx == dz / dz

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

c 精度 浮点转换

评论

0赞 Russell Borogove 5/7/2015
一个好的编译器应该识别 dx/dx,而不是实际发出除法指令。
0赞 Eric J. 5/7/2015
您可以精确地将 2^53 + 1 以下的任何值表示为双精度值。除此之外,您还会遇到舍入错误,即使对于整数类型也是如此。stackoverflow.com/a/1848762/141172
0赞 user3629249 5/7/2015
你可能还记得,从你的小学时代开始,一个数字除以它自己就是 1,所以比较“可能”有效。但是,一般来说,绝不应该使用“==”来比较浮点数,而是获取绝对值,获得差值,检查差值小于某个 threashold
0赞 chux - Reinstate Monica 5/7/2015
(dx * dy) * dz == dx * (dy * dz)如果精度<精度的两倍,则会出现问题 - 这通常是这种情况。 不太可能成为问题,因为精度肯定超过精度 + 1。 明显的问题应该或.doubleint(dx + dy) + dz == dx + (dy + dz)doubleintdx / dx == dz / dzdx==0dz==0
0赞 douyu 12/1/2021
当和大于时,它可能有精度问题。 for 是错误的。dx * dydy * dz2^53double dx = (double)(INT_MAX); double dy = (double)(INT_MAX - 0x111111); double dz = (double)(INT_MAX - 0xabcd);(dx * dy) * dz == dx * (dy * dz)

答:

1赞 Yu Hao 5/7/2015 #1

假设最多为 32 位,并遵循 IEEE-754。 最多可以精确存储 253 个整数值。intdoubledouble


在添加的情况下:

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

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


而在乘法的情况下:

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

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

评论

0赞 cheng 5/7/2015
澄清一下,所以 double 可以存储的最大值是 2^53 的原因是因为 52 位尾数 + 隐含的前导 1?
0赞 chux - Reinstate Monica 5/7/2015
需要明确的是:可以精确地存储所有整数 --inclusive - 就像一个 54 位有符号整数或 .double-pow(2,53) ... +pow(2,53)int54_t
1赞 Russell Borogove 5/7/2015 #2

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

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

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

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

评论

0赞 user3629249 5/7/2015
指数还有一个内置的偏移量(我认为是 256),以允许正指数和负指数,而不必为符号消耗一点
0赞 Russell Borogove 5/7/2015
指数偏移量(通常称为偏差)是指数范围的一半。对于具有 11 位指数的 IEEE double,偏差为 1023。对于IEEE单曲,它是127。