C中的浮点减法结果为零

4 c floating-point subtraction

我有用C编写的代码,用于16位微控制器.代码本质上做了很多浮点运算.

算法工作正常,直到结果为正,但在减法的情况下,如果预期结果为负,我得到零.

result = 0.005 - 0.001;      Is correctly computed as 0.004
result = 0.001 - 0.005;      Is always zero.
Run Code Online (Sandbox Code Playgroud)

为什么浮动有这样的行为?

pax*_*blo 5

有趣.它很容易成为浮点软件的错误.嵌入式系统通常包括浮点作为选项,以便保持代码大小.

因为你的第一个声明有效,我不确定这里的问题是什么.

会发生什么:

result = 0.005 - 0.001;
result = -result;

result = 0.002 - 0.001;
result = 0.002 - 0.002;
result = 0.002 - 0.003;

result = 0.001 - 0.002;
result = 0.001 - 0.003;
result = 0.001 - 0.004;
Run Code Online (Sandbox Code Playgroud)

这里的想法是收集有关可能导致它的原因的有用信息,这是法医学中常见的事情.这些计算的结果可能有助于确定实际问题.

根据您在评论中的结果:

result = 0.005 - 0.001;  // 0.004
result = -result;        // 0.000
result = 0.002 - 0.001;  // 0.001
result = 0.002 - 0.002;  // 0.000
result = 0.002 - 0.003;  // 0.000
result = 0.001 - 0.002;  // 0.000
result = 0.001 - 0.003;  // 0.000
result = 0.001 - 0.004;  // 0.000
Run Code Online (Sandbox Code Playgroud)

看起来你的浮点库有一个严重的缺点.还有两个问题:

  • 你如何打印出结果(向我们展示实际的代码)?
  • 您使用的是哪种微控制器和开发环境?

您的打印方式可能存在一些问题,或者可能是您环境的限制.

Ajit,我想你真的要给我们一些代码来帮助你.不一定是你的真实代码(你对发布真实代码的关注是理解的),只是一些证明问题.

根据您的一些评论,即:

Adriaan,"result"的数据类型是float,即32位表示(单个).我有CAN作为系统接口,因此我将结果乘以1000以通过CAN总线发送它.如果它恰好是负数,如-0.003,那么我期待CAN消息中的FF FD.我没有调试器.

我不确定我完全理解,但我会试一试.

你有一个32位浮点数,例如-0.003,你将它乘以1000 并将它放在一个整数(0xFFFD是-3位的16位二进制补码表示).那么当你运行类似下面的代码时会发生什么:

int main(void) {
    float w = -0.003;
    int x = (int)(w * 1000);
    int y = -3;
    int z = -32768;
    // Show us you code here for printing x, y and z.
    return 0;
}
Run Code Online (Sandbox Code Playgroud)

我希望你测试整数的原因是它可能与浮点数无关.可能浮动值完全正确,但是打印方式存在一些问题(CAN方法).

如果"CAN"是某种串行接口,则可能对允许通过它发送的字节有限制.我可以设想一种情况,其中高字节用作数据包标记,以便FF可能实际上过早地结束消息.这就是为什么我还要你测试-32768(0x8000).

很难相信STMicroelectronics会产生这样一个无法处理负浮动的脑死亡运行系统.我觉得信息在其他地方被破坏似乎更有可能(例如,"打印"过程,无论可能是什么).