使用 uint16_t 进行操作而未显式转换为 float 时出现意外结果

Ric*_*ins 2 c floating-point gcc ieee-754

我正在做一些操作,但没有找到确切的解释来解释为什么我发现了特定的行为。语境:

  • 我收到一个值 (24.2),然后计算一些偏移和增益
  • 然后将结果通过 CAN 发送。

最小工作示例:

#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;
}
Run Code Online (Sandbox Code Playgroud)

我知道使用 float 时无法准确表达该值。因此,用实际表示IEEE-754 的值来截断,以防万一并且是正确的。24.2 is24.200000762939453125ce

为什么 case a, b,d会产生意想不到的值?(我知道强制转换可以解决问题,但我想了解原因)

dbu*_*ush 5

该常量24.2的类型为double,其值约为 24.1999999999999993。因此除以 0.1 大约得到 241.9999999999999716 并将该值转换为整数类型会截断为 241。

当您转换24.2为 type时float,最接近的表示形式是 24.2000007629394531,除以 0.1 得到 242.0000076293945312,它被截断为 242。