此问题在此处已有答案:
(31个答案)
5天前关闭。
我使用的是在线编译器https://www.onlinegdb.com/,在下面的代码中,当我将2.1乘以100时,输出变为209而不是210。
#include<stdio.h>
#include <stdint.h>
int main()
{
float x = 1.8;
x = x + 0.3;
int coefficient = 100;
printf("x: %2f\n", x);
uint16_t y = (uint16_t)(x * coefficient);
printf("y: %d\n", y);
return 0;
}
我做错了什么?我应该怎么做才能得到210?
我尝试了所有不同的类型转换仍然不工作。
3条答案
按热度按时间col17t5w1#
下面假设编译器对
float
和double
使用IEEE-754 binary 32和binary 64,这是非常常见的。float x = 1.8;
由于
1.8
是一个double
常量,编译器会将1.8转换为最接近的double
值1.800000000000000444089209850062616169452667236328125。然后,为了将其赋给float
x
,编译器会将其转换为最接近的float
值。1.7999999523162841796875.x = x + 0.3;
编译器将0.3转换为最接近的
double
值0.299999999999999988897769753748434595763683319091796875。然后,它使用double
算法将x
与该值相加。其产生2.0999995231628400205181605997495353221893310546875。然后,为了将其赋值给
x
,它将其转换为最接近的float
值2.09999904632568359375。uint16_t y = (uint16_t)(x * coefficient);
因为
x
是float
,coefficient
是int
,所以编译器将coefficient
转换为float
,并使用float
算法执行乘法,结果为209.9999847412109375。然后转换为
uint16_t
会截断该数字,生成209。得到210的一种方法是使用
uint16_t y = lroundf(x * coefficient);
。(lroundf
在<math.h>
中声明。)然而,为了确定正确的方法,您应该解释这些数字是什么以及为什么要使用它们进行此运算。3htmauhk2#
浮点数并不精确,当您将1.8 + 0.3相加时,FPU可能会生成与预期的2.1略有不同的结果(差值小于浮点数Epsilon)阅读更多关于wiki https://en.wikipedia.org/wiki/Machine_epsilon中浮点数表示的信息
你的情况是
1.8+ 0.3 = 209.0999999 ...然后将其截断为整数,得到209
您可能会发现此问题也与您相关Why float.Epsilon and not zero?可能是
dgenwo3n3#