我正在做一些操作,但没有找到确切的解释来解释为什么我发现了特定的行为。 背景:
最小工作示例:
#include <stdio.h>
#include <stdint.h>
int main()
{
printf("Operations with comas \n");
uint16_t a = (uint16_t)((24.2 - 0)/0.1); /* 241 Incorrect*/
uint16_t b = (uint16_t)((24.2 - 0.0)/0.1); /* 241 Incorrect */
uint16_t c = (uint16_t)((float)(24.2 - 0)/0.1); /* 242 Correct */
uint16_t d = (uint16_t)(24.2/0.1); /* 241 Incorrect*/
uint16_t e = (uint16_t)(242.0); /* 242 Correct */
printf("a %u \n" , a);
printf("b %u \n" , b);
printf("c %u \n" , c);
printf("d %u \n" , d);
printf("e %u \n" , e);
return 0;
}
我知道使用 float 时无法准确表达该值。与
IEEE-754
24.2 is
的值实际上代表 24.200000762939453125
,因此 c
和 e
情况下的截断是正确的。
为什么情况
a
、b
、d
会产生意想不到的值? (我知道强制转换可以解决问题,但我想了解原因)
根据 C 标准,无后缀的浮点常量的类型为
double
,而不是 float
,因此代码中所有带点的常量都是 double
,其他所有内容都会提升为 double
。
采用以下代码(注意第二个表达式的值上的后缀
f
):
#include <stdio.h>
#include <inttypes.h>
int main(void) {
uint16_t a = (uint16_t)((24.2 - 0)/0.1);
uint16_t b = (uint16_t)((24.2f - 0)/0.1f);
printf("%hu %hu\n", a, b);
}
输出为:
241 242
所以这里的重点是,因为使用了不同的浮点精度,所以发生了不同的近似值。
常量
24.2
的类型为 double
,其值约为 24.1999999999999993。因此除以 0.1 大约得到 241.9999999999999716 并将该值转换为整数类型会截断为 241。
将
24.2
转换为 float
时,最接近的表示形式为 24.2000007629394531。