C 中的浮点减法结果为零
我有用 C 语言编写的代码,适用于 16 位微控制器。该代码本质上执行大量浮点运算。
在结果为正之前,算术工作正常,但在减法的情况下,如果预期结果为负,我会得到零。
result = 0.005 - 0.001; Is correctly computed as 0.004
result = 0.001 - 0.005; Is always zero.
为什么浮动会有这样的行为?
I have code written in C which is intended for a 16-bit microcontroller. The code essentially does lot of floating point arithmetic.
The arithmetic works fine till the result is positive, but in case of subtraction, if the expected result is negative, I get a zero.
result = 0.005 - 0.001; Is correctly computed as 0.004
result = 0.001 - 0.005; Is always zero.
Why is there such a behavior for float?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
有趣的。这很可能是浮点软件中的错误。嵌入式系统通常包含浮点作为选项,以减少代码大小。
我不确定这就是这里的问题,因为你的第一个声明有效。
发生了什么:
这里的想法是收集有用的信息,了解可能导致这种情况的原因,这是取证中常见的事情。这些计算的结果可能有助于确定实际问题。
根据您在评论中的结果:
看起来您的浮点库有一个严重的缺点。还有两个问题:
您的打印方式可能存在一些问题,或者可能是您的环境的限制。
阿吉特,我认为你真的必须给我们一些代码来帮助你。不一定是您的真实代码(您对发布真实代码的担忧是可以理解的),只是一些演示问题的代码。
根据您的一些评论,即:
我不确定我是否完全理解,但我会尝试一下。
您有一个 32 位浮点数,例如 -0.003,将其乘以 1000,然后将其放入整数(0xFFFD 是 -3 的 16 位二进制补码表示形式)。那么,当您运行类似以下代码的代码时会发生什么:
我希望您测试整数的原因是它可能与浮点数完全无关。浮点值可能完全正确,但打印它的方式(CAN 方法)存在一些问题。
如果“CAN”是某种串行接口,则可能对允许通过它发送的字节有限制。我可以设想一种场景,其中高字节用作数据包标记,以便 FF 实际上可能提前结束消息。这就是为什么我还希望您测试-32768 (0x8000)。
很难相信 STMicroElectronics 会生产出如此脑残的运行时系统,无法处理负数漂浮。在我看来,信息更有可能在其他地方被破坏(例如,“打印”过程,无论是什么)。
Interesting. It could quite easily be a fault in the floating point software. Embedded systems often include floating point as an option so as to keep the code size down.
I'm not sure that's the problem here though since your first statement works.
What happens with:
The idea here is to collect useful information as to what could be causing it, a common thing to do in forensics. The results of those calculations are likely to be helpful in determining the actual problem.
Based on your results in the comments:
It looks like your floating point library has a serious shortcoming. Two more questions:
There may be some problem with the way you're printing or it may be a limitation of your environment.
Ajit, I think you're really going to have to give us some code to help you out. Not necessarily your real code (your concern about releasing the real code is understood), just some that demonstrates the problem.
Based on some of your comments, to wit:
I'm not sure I totally understand, but I'll give it a shot.
You have a 32-bit float, for example, -0.003 and you multiply it by 1000 and put it in an integer (0xFFFD is the 16-bit two's complement representation of -3). So what happens when you run something like the following code:
The reason I want you to test an integer is that it may have nothing to do with floats at all. It may be that the float value is perfectly correct, but there's some problem with the way you're printing it (the CAN method).
If "CAN" is some sort of serial interface, it may be there's a restriction on the bytes you're allowed to send across it. I can envisage a scenario where the high bytes are used as packet markers so that FF may actually end the message prematurely. That's why I also want you to test -32768 (0x8000).
It's hard to believe that STMicroelectronics would produce such a braindead runtime system that it couldn't handle negative floats. It seems much more likely to me that the information is being corrupted somewhere else (for example, the "printing" process, whatever that may be).
微控制器有浮点硬件吗?可能不会;微控制器通常不会。因此,这可能是浮点运算软件实现中的错误或限制。查找文档,和/或阅读源代码(如果有)。
Does the microcontroller have hardware for floating-point? Probably not; microcontrollers generally don't. So, this might be a bug or limitation in the software implementation of floating-point arithmetic. Look for documentation, and/or read the source if you have it.
您是否可能尝试将 0.001 - 0.005 的结果打印为 5 个字符字段?如果是这样,结果将显示为四舍五入到 0.0。
Is it possible that you are trying to print out the result of 0.001 - 0.005 as a 5 character field? If so, the result will be displayed as rounded to 0.0.
您能提供更多背景信息吗?在此示例中,评估可能由编译器完成,因为两个常量在编译时都是已知的。 “结果”的类型是什么? (即 IEEE-754 半或单或双?)您如何评价这?使用调试器、if 语句还是使用 printf?我之所以问这个问题,是因为可能存在转移注意力的情况。例如,如果您使用 printf 的格式不正确,您可能只是看不到减号。当您查看二进制表示形式(即,如果是 32 位,则通过 printf("%lx", result))并检查符号位。
Can you provide more context? In this example, the evaluation is propably done by the compiler as both constants are known at the time of compilation. What is the type of 'result'? (i.e. IEEE-754 half or single or double?) How do you evaluate this? Using a debugger, if-statement or with a printf? The reason I'm asking this is because there may be a red herring. For instance if you format incorrectly using printf, you may just not see the minus sign. When you take a look at the binary representation (i.e. by printf("%lx", result) if it is 32-bit) and check the sign bit.
它本质上不是 C 的东西,所以这取决于你没有说过的事情: -
是否是您从浮点转换为您尚未显示的 int 的转换?
It's not an inherently C thing, so it's down to the things you haven't said:-
Could it be your cast converting from floating point to an int that you haven't shown?