我有用C编写的代码,用于16位微控制器。代码本质上做了很多浮点运算。
算法工作正常,直到结果为正,但在减法的情况下,如果预期结果为负,我得到零。
result = 0.005 - 0.001; Is correctly computed as 0.004
result = 0.001 - 0.005; Is always zero.
为什么浮动有这样的行为?
答案 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事物,所以这取决于你没有说过的事情: -
是否可以将您的转换从浮点转换为未显示的int?