我有用 C 编写的代码,用于 16 位微控制器。该代码本质上做了很多浮点运算。
算术工作正常,直到结果为正,但在减法的情况下,如果预期结果为负,我得到一个零。
result = 0.005 - 0.001; Is correctly computed as 0.004
result = 0.001 - 0.005; Is always zero.
为什么浮动会有这样的行为?
我有用 C 编写的代码,用于 16 位微控制器。该代码本质上做了很多浮点运算。
算术工作正常,直到结果为正,但在减法的情况下,如果预期结果为负,我得到一个零。
result = 0.005 - 0.001; Is correctly computed as 0.004
result = 0.001 - 0.005; Is always zero.
为什么浮动会有这样的行为?
有趣的。它很容易成为浮点软件的故障。嵌入式系统通常包括浮点作为选项,以降低代码大小。
我不确定这是这里的问题,因为你的第一个陈述有效。
会发生什么:
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,“结果”的数据类型是浮点数,即 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;
}
我希望您测试整数的原因是它可能与浮点数无关。浮点值可能是完全正确的,但是您打印它的方式(CAN 方法)存在一些问题。
如果“CAN”是某种串行接口,则可能对您允许通过它发送的字节有限制。我可以设想一个场景,其中高字节用作数据包标记,以便 FF 实际上可能过早地结束消息。这就是为什么我还希望你测试 -32768 (0x8000)。
很难相信意法半导体会生产出这样一个无法处理负浮点数的脑死运行时系统。在我看来,信息在其他地方被破坏的可能性更大(例如,“打印”过程,无论是什么)。
微控制器是否有浮点硬件?可能不是; 微控制器通常不会。因此,这可能是浮点运算的软件实现中的错误或限制。查找文档,和/或阅读源代码(如果有)。
您是否有可能尝试将 0.001 - 0.005 的结果打印为 5 个字符的字段?如果是这样,结果将显示为四舍五入到 0.0。
你能提供更多的上下文吗?在此示例中,评估可能由编译器完成,因为这两个常量在编译时都是已知的。“结果”的类型是什么?(即IEEE-754一半或单或双?)你如何评价这个?使用调试器、if 语句还是 printf?我问这个的原因是因为可能有一个红鲱鱼。例如,如果您使用 printf 格式不正确,您可能只是看不到减号。当您查看二进制表示(即 printf("%lx", result) 如果它是 32 位)并检查符号位时。
这不是本质上 C 的东西,所以它取决于你没有说的话:-
可能是您的演员从浮点转换为您未显示的 int 吗?