C 将双精度结果直接指定给整数时的精度损失/舍入差
在这种情况下,从double转换为int是否会按预期执行C 将双精度结果直接指定给整数时的精度损失/舍入差,c,math,casting,double,precision,C,Math,Casting,Double,Precision,在这种情况下,从double转换为int是否会按预期执行 double value = 45.33; double multResult = (double) value*100.0; // assign to double int convert = multResult; // assign to int printf("convert = %d\n", convert); // prints 4533 as expected double v
double value = 45.33;
double multResult = (double) value*100.0; // assign to double
int convert = multResult; // assign to int
printf("convert = %d\n", convert); // prints 4533 as expected
double value = 45.33;
int multResultInt = (double) value*100.0; // assign directly to int
printf("multResultInt = %d\n", multResultInt); // prints 4532??
但在这种情况下并非如此:
double value = 45.33;
double multResult = (double) value*100.0; // assign to double
int convert = multResult; // assign to int
printf("convert = %d\n", convert); // prints 4533 as expected
double value = 45.33;
int multResultInt = (double) value*100.0; // assign directly to int
printf("multResultInt = %d\n", multResultInt); // prints 4532??
在我看来,应该没有什么区别。在第二种情况下,在转换为int之前,结果仍然首先存储为double,除非我不理解强制转换和硬赋值之间的一些区别。这两者之间确实没有区别,但编译器在涉及浮点计算时会有一些自由度。例如,编译器可以自由地对中间计算结果使用更高的精度,但更高的精度仍然意味着不同,因此结果可能会有所不同 一些编译器提供了开关,用于始终降低额外精度,并将所有中间结果转换为规定的浮点数(例如64位双精度数)。但是,这会使代码变慢 在特定情况下,数字
45.33
不能用浮点值精确表示(用二进制表示时,它是一个周期数,需要无限位)。当乘以100
时,该值可能是,但不是整数,而是非常接近的值(刚好低于或正好高于)
int
使用截断执行转换或强制转换,非常接近4533
但下面的内容将变为4532
,而上面的内容将变为4533
;即使差异非常小,比如说1E-300
为避免出现问题,请务必考虑数值精度问题。如果您的计算依赖于浮点数的精确值,那么您使用的工具是错误的。这两者之间确实没有区别,但是编译器在涉及浮点计算时会有一些自由度。例如,编译器可以自由地对中间计算结果使用更高的精度,但更高的精度仍然意味着不同,因此结果可能会有所不同 一些编译器提供了开关,用于始终降低额外精度,并将所有中间结果转换为规定的浮点数(例如64位双精度数)。但是,这会使代码变慢 在特定情况下,数字
45.33
不能用浮点值精确表示(用二进制表示时,它是一个周期数,需要无限位)。当乘以100
时,该值可能是,但不是整数,而是非常接近的值(刚好低于或正好高于)
int
使用截断执行转换或强制转换,非常接近4533
但下面的内容将变为4532
,而上面的内容将变为4533
;即使差异非常小,比如说1E-300
为避免出现问题,请务必考虑数值精度问题。如果你所做的计算依赖于浮点数的精确值,那么你使用的工具是错误的。@6502为你提供了理论,下面是如何通过实验来看待问题
double v = 45.33;
int x = v * 100.0;
printf("x=%d v=%.20lf v100=%.20lf\n", x, v, v * 100.0 );
在我的机器上,这个打印
x=4533 v=45.32999999999999829470 v100=4533.00000000000000000000
当编码为64位IEEE-754浮点数时,值45.33
没有精确表示。由于编码精度有限,v
的实际值略低于预期值
那么为什么乘以100.0
可以解决某些机器上的问题呢?一种可能性是乘法以80位的精度完成,然后四舍五入以适应64位的结果。当转换为64位时,80位数字4532.999…
将四舍五入为4533
在您的机器上,乘法显然是以64位的精度完成的,我希望
v100
将打印为4532.999…
@6502给出了理论,下面是如何通过实验来看待事物
double v = 45.33;
int x = v * 100.0;
printf("x=%d v=%.20lf v100=%.20lf\n", x, v, v * 100.0 );
在我的机器上,这个打印
x=4533 v=45.32999999999999829470 v100=4533.00000000000000000000
当编码为64位IEEE-754浮点数时,值45.33
没有精确表示。由于编码精度有限,v
的实际值略低于预期值
那么为什么乘以100.0
可以解决某些机器上的问题呢?一种可能性是乘法以80位的精度完成,然后四舍五入以适应64位的结果。当转换为64位时,80位数字4532.999…
将四舍五入为4533
在您的机器上,乘法显然是以64位的精度完成的,我希望
v100
将打印为4532.999…
只需提及,(double)
强制转换是多余的。对我来说,两者都是相同的,您使用哪种编译器?()当您删除(double)
强制转换时,是否会得到相同的行为?在这两种情况下,强制转换仅适用于值
,该值已经是双精度
类型。(间距有误导性;强制转换比*
操作符绑定得更紧密。)编译器版本:gcc版本4.6.3(Ubuntu/Linaro 4.6.3-1ubuntu5)只是提到,(double)
强制转换是多余的。对我来说,两者都是相同的,你使用哪种编译器?()当您删除(double)
强制转换时,是否会得到相同的行为?在这两种情况下,强制转换仅适用于值
,该值已经是双精度
类型。(间距有误导性;强制转换比*
运算符绑定得更紧密。)编译器版本:gcc版本4.6.3(Ubuntu/Linaro 4.6.3-1ubuntu5)