C中的浮点减法结果为零

时间:2009-09-08 06:59:02

标签: 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.

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

5 个答案:

答案 0 :(得分: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;

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

根据您在评论中的结果:

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

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

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

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

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;
}

我希望你测试一个整数的原因是它可能只有 nothing 来处理浮点数。可能浮动值完全正确,但是打印方式存在一些问题(CAN方法)。

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

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

答案 1 :(得分:0)

微控制器是否具有浮点硬件?可能不是;微控制器通常不会。因此,这可能是浮点运算的软件实现中的错误或限制。查找文档,和/或阅读源文件。

答案 2 :(得分:0)

您是否可能尝试将0.001 - 0.005的结果打印为5个字符的字段?如果是这样,结果将显示为舍入为0.0。

答案 3 :(得分:0)

您能提供更多背景信息吗?在此示例中,评估由编译器可行地完成,因为两个常量在编译时是已知的。 '结果'的类型是什么? (即IEEE-754一半或单身或双人?)你如何评价这个?使用调试器,if语句或printf?我问这个的原因是因为可能有一个红鲱鱼。例如,如果使用printf格式不正确,则可能看不到减号。当你看一下二进制表示(即printf(“%lx”,结果),如果它是32位)并检查符号位。

答案 4 :(得分:0)

这不是一个固有的C事物,所以这取决于你没有说过的事情: -

  • 控制器(显然是ST10)
  • 编译器(宇宙软件?如果符合标准)
  • 浮点库(来自编译器?)
  • 该程序(最短的完整程序,证明它会很好。)

是否可以将您的转换从浮点转换为未显示的int?