Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/68.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C 浮点加法/乘法/除法_C_Floating Point_Floating Accuracy_Floating Point Conversion - Fatal编程技术网

C 浮点加法/乘法/除法

C 浮点加法/乘法/除法,c,floating-point,floating-accuracy,floating-point-conversion,C,Floating Point,Floating Accuracy,Floating Point Conversion,我在做课本上的一些家庭作业,对某些算术运算的浮点舍入/精度有一些问题 如果我用这样的整型铸造双打: int x = random(); double dx = (double) x; 假设变量y、z、dy和dz遵循相同的格式 那么,我们希望: (dx + dy) + dz == dx + (dy + dz) (dx * dy) * dz == dx * (dy * dz) 联想?我知道,如果我们有分数表示,那么它就不会有关联性,因为根据哪些操作数彼此相加/相乘,舍入会损失一些精度。然而,由

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

如果我用这样的整型铸造双打:

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这样的操作可以产生0.999…9,但没有足够的信息来解释这是如何发生的,或者它是否会随其他部门的操作而变化

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


在添加的情况下:

(dx + dy) + dz == dx + (dy + dz)
==
的两边都有精确的值,因此它是关联的


而在乘法的情况下:

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

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

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

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

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


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

一个好的编译器应该识别dx/dx,而不是实际发出除法指令。您可以准确地将最大为2^53+1的任何值表示为双精度。除此之外,您还会遇到舍入错误,即使对于整数类型也是如此。你可能还记得,从小学时代起,一个数字除以它本身就是1,所以比较“可能”是有效的。但是,一般情况下,不应使用“==”来比较浮点数,而是应获取绝对值,获取差值,检查差值是否小于某个threshold
(dx*dy)*dz==dx*(dy*dz)
如果
的精度是
int
精度的两倍,这是一个问题-通常情况下
(dx+dy)+dz==dx+(dy+dz)
不太可能是个问题,因为
的精度比
int
的精度+1高一倍
dx/dx==dz/dz
明显的问题应该是
dx==0
dz==0
。指数还有一个内置的偏移量(我想是256),允许正指数和负指数,而不必为符号消耗一点。指数偏移量(通常称为偏差)是指数范围的一半。对于指数为11位的IEEE double,偏差为1023。对于IEEE single,它是127。只是澄清一下,所以双精度can存储的最大值是2^53的原因是52位尾数+隐含的前导1?要清楚:
double
可以精确存储所有整数
-pow(2,53)+pow(2,53)
--包括在内-就像54位有符号整数或
int54\u t