Warning: file_get_contents(/data/phpspider/zhask/data//catemap/4/c/65.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_Math_Casting_Double_Precision - Fatal编程技术网

C 将双精度结果直接指定给整数时的精度损失/舍入差

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转换为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 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)