对于一般原则,paxdiablo 的答案包含相关部分。大多数终止小数不能精确表示为二进制浮点数,因此浮点变量的值比给定字符串中数字表示的数学值稍小或稍大,因此当您想要获得适当的整数时缩放后的值,你应该四舍五入而不是截断。
但是在这里的具体例子中,我们有一个不同的场景。最接近 1441.1441 的 IEEE754 双精度(64 位二进制)值是
1441.14409999999998035491444170475006103515625
这确实比 1441.1441 小一点。但如果将该值乘以 10000 作为 IEEE754 双精度值,则结果正好是
14411441
这里发生的情况是,如 5.2.4.2.2 第 9 段所允许的那样
除了赋值和强制转换(删除所有额外的范围和精度)之外,具有浮动操作数的运算符产生的值和经过通常算术转换的值和浮动常量的值被评估为范围和精度可能大于要求的格式类型。
(强调我的),乘积的计算精度比类型(可能是 x87 80 位格式)要求的精度更高,产生的值略小,当乘法的结果转换为int
时,小数部分被丢弃,你得到 14411440。
scanf("%lf",&num);
该值存储在 中num
,因此它的精度必须为double
。
tmp=num*10000;
该产品num * 10000
既不存储也不转换为double
,因此它可能具有更高的精度,从而导致比最接近的值更小或更大的double
值。然后截断该值以获得int
.
如果您将产品存储在double
变量中
num *= 10000;
tmp = num;
或double
在转换为之前将其转换为int
,
tmp = (double)(num * 10000);
您应该得到输入的结果 14411441 1441.1441
(但请注意,并非所有编译器在转换或存储时总是遵守转换为所需精度的要求 - 违反标准 - 所以不能保证所有优化设置都会产生 14411441 )。
由于许多 64 位平台使用 SSE 指令而不是 x87 协处理器执行浮点运算,因此观察到的行为不太可能出现在 64 位系统上而不是 32 位系统上。