C 计算双精度的范围
作为“C编程语言”练习的一部分,我试图找到一种方法来计算计算机上的最大可能浮点和最大可能双精度。下面显示的技术适用于C 计算双精度的范围,c,floating-point,C,Floating Point,作为“C编程语言”练习的一部分,我试图找到一种方法来计算计算机上的最大可能浮点和最大可能双精度。下面显示的技术适用于floats(计算最大浮动),但不适用于double: // max float: float f = 1.0; float last_f; float step = 9.0; while(1) { last_f = f; f *= (1.0 + step); while (f == INFINITY) { step /= 2.0;
float
s(计算最大浮动),但不适用于double
:
// max float:
float f = 1.0;
float last_f;
float step = 9.0;
while(1) {
last_f = f;
f *= (1.0 + step);
while (f == INFINITY) {
step /= 2.0;
f = last_f * (1.0 + step);
}
if (! (f > last_f) )
break;
}
printf("calculated float max : %e\n", last_f);
printf("limits.h float max : %e\n", FLT_MAX);
printf("diff : %e\n", FLT_MAX - last_f);
printf("The expected value? : %s\n\n", (FLT_MAX == last_f)? "yes":"no");
// max double:
double d = 1.0;
double last_d;
double step_d = 9.0;
while(1) {
last_d = d;
d *= (1.0 + step_d);
while (d == INFINITY) {
step_d /= 2.0;
d = last_d * (1.0 + step_d);
}
if (! (d > last_d) )
break;
}
printf("calculated double max: %e\n", last_d);
printf("limits.h double max : %e\n", DBL_MAX);
printf("diff : %e\n", DBL_MAX - last_d);
printf("The expected value? : %s\n\n", (DBL_MAX == last_d)? "yes":"no");
这将导致:
calculated float max : 3.402823e+38
limits.h float max : 3.402823e+38
diff : 0.000000e+00
The expected value? : yes
calculated double max: 1.797693e+308
limits.h double max : 1.797693e+308
diff : 1.995840e+292
The expected value? : no
在我看来,在第二种情况下,它仍然使用单一精度进行计算
我缺少什么?文本为n.0的表达式都是双精度浮点类型。这允许使用更高精度的中间值计算f的赋值 正是这种效应使得算法能够在浮点情况下收敛 对于严格的双精度浮点,这种收敛是不可能的 如果在float情况下对文本使用了f后缀,那么也不会发生收敛
如果您的平台具有更宽的long double类型,修复方法是在文本上使用long double后缀。具有文本n.0的表达式都是双精度浮点类型。这允许使用更高精度的中间值计算f的赋值 正是这种效应使得算法能够在浮点情况下收敛 对于严格的双精度浮点,这种收敛是不可能的 如果在float情况下对文本使用了f后缀,那么也不会发生收敛
如果您的平台具有较宽的long double类型,修复方法是在文本上使用long double后缀。OP的方法在第一种情况下以比
float
更宽的精度进行计算,在第二种情况下以比double
更宽的精度进行计算时有效
在第一种情况下,OP报告FLT\u EVAL\u METHOD==0
因此float
计算按float
进行,double
计算按double
进行。请注意,float步骤。。。1.0+步骤
是一个双重
计算
下面的代码强制计算加倍,因此即使使用
FLT\u EVEL\u METHOD==2,我也可以复制OP的问题(内部计算使用long double
)
相反,当步骤d
很小时,OP应该使用以下方法,而不是形成步骤d*最后一个步骤d
的不精确的和1.0+步骤d
,而是形成步骤d*最后一个步骤d
的精确的乘积。第二种形式通过在d
中提供额外的计算精度位,使新d
的计算更加精确。采用OP方法不需要更高精度的FP
d = last_d + step_d*last_d;
diff : 0x0p+0 0.000000e+00
The expected value? : yes
在第一种情况下,OP的方法适用于精度大于float
的计算,在第二种情况下适用于精度大于double
的计算
在第一种情况下,OP报告FLT\u EVAL\u METHOD==0
因此float
计算按float
进行,double
计算按double
进行。请注意,float步骤。。。1.0+步骤
是一个双重
计算
下面的代码强制计算加倍,因此即使使用FLT\u EVEL\u METHOD==2,我也可以复制OP的问题(内部计算使用long double
)
相反,当步骤d
很小时,OP应该使用以下方法,而不是形成步骤d*最后一个步骤d
的不精确的和1.0+步骤d
,而是形成步骤d*最后一个步骤d
的精确的乘积。第二种形式通过在d
中提供额外的计算精度位,使新d
的计算更加精确。采用OP方法不需要更高精度的FP
d = last_d + step_d*last_d;
diff : 0x0p+0 0.000000e+00
The expected value? : yes
我认为它适用于float,因为有些比较是以双精度进行的。提示:使用%a“
查看last\u d/DBL\u MAX
@Bathsheba的所有详细信息-是的,我想也是这样,只是现在还不知道如何解决这个问题:)我打赌我的工作就是解决这个问题-回答如下。我看到的问题是d=last\u d*(1.0+step\d)代码>vs.可能d=last\u d+step\u d*last\u d
作为第一个可以使加倍中间和1.0+步骤d
,即1.0
,即使没有步骤d!=0
而第二种形式可以使用更宽一点的FP数学。您是否使用d=last\u d+step\u d*last\u d代码>?我认为它适用于float,因为有些比较是以双精度进行的。提示:使用%a“
查看last\u d/DBL\u MAX
@Bathsheba的所有详细信息-是的,我想也是这样,只是现在还不知道如何解决这个问题:)我打赌我的工作就是解决这个问题-回答如下。我看到的问题是d=last\u d*(1.0+step\d)代码>vs.可能d=last\u d+step\u d*last\u d
作为第一个可以使加倍中间和1.0+步骤d
,即1.0
,即使没有步骤d!=0
而第二种形式可以使用更宽一点的FP数学。您是否使用d=last\u d+step\u d*last\u d代码>?为什么局部变量被标记为易变的
?这就是迫使计算使用双精度的原因吗?@Groo是的,部分。如果我的double
变量不是volatile
,那么使用FLT\u EVEL\u METHOD==2
,可能会出现各种FP数学,精度更高。因此,尝试强制计算只在double
处进行,并将last_f*(1.0+步)
分为两步,确保1.0+步
总和不会以更高的精度在内部保留。然后使用d=last\ud+步骤d*last\ud重新形成代码代码>(甚至v