简体   繁体   English

嵌入式系统中的浮点错误

[英]floating point bug in embedded system

On a Rabbit microcontroller.. (1) I am incrementing f1 every second by converting into hours to the existing value and store in the same register. 在Rabbit微控制器上..(1)通过将小时数转换为现有值并存储在同一寄存器中,我每秒增加f1。

void main()
{
    float f1;
    int i;
    f1 = 4096;
    // Assume that I am simulating a one second through each iteration of the following loop
    for(i = 0; i < 100; i++)
    {
        f1 += 0.000278; // f1 does not change from 4096
        printf("\ni: %d f1: %.06f", i, f1);
    }
}

(2) Another question is when I try to store a 32-bit unsigned long int value into float variable and accessing it does not give me the value I have stored. (2)另一个问题是,当我尝试将32位无符号long int值存储到float变量中时,访问它并没有给我存储的值。 What am I doing wrong? 我究竟做错了什么?

void main()
{
    unsigned long L1;
    int temp;
    float f1;

    L1 = 4000000000; // four billion
    f1 = (float)L1;

    // Now print both
    // You see that L1: 4000000000 while f1: -4000000000.000000
    printf("\nL1: %lu f1:%.6f", L1, f1);
}

The first problem is that single precision (32 bit) binary floating point is good for only approximately 6 significant figures in decimal. 第一个问题是单精度(32位)二进制浮点数仅适合约6位十进制有效数字。 So if you start with 4096.00 anything less than .01 cannot be added to the value. 因此,如果您从4096.00开始,则不能将小于.01的值添加到该值中。 Using double precision will improve the result at some significant cost. 使用双精度将以一定的成本提高结果。

It is usually unnecessary and inappropriate to use floating point, it is very expensive on a processor without an FPU - especially an 8 bitter. 通常不需要使用浮点数,也不适合使用浮点数,这在没有FPU的处理器上非常昂贵-尤其是8位苦味。 Moreover your literal approximation of one second in hours (1.0f/3600.0f hours) will introduce significant cumulative error in any case. 此外,在任何情况下,您的小时数(1.0f / 3600.0f小时)的字面近似值都会引入明显的累积误差。 You may be better off storing time in integer seconds, and converting to hours where necessary for display or output. 您最好将时间存储为整数秒,并在需要进行显示或输出时将其转换为小时。

The second problem is less clear, but seems likely to be an issue with the Rabbit compiler implementation of floating point or possibly of the %f format specifier in the printf() implementation. 第二个问题尚不清楚,但似乎是Rabbit编译器实现的浮点问题,或者可能是printf()实现中的%f格式说明符。 Check the ISO compliance statement in the compiler documentation - there may be restrictions - especially on floating point. 检查编译器文档中的ISO符合性声明-可能会有限制-特别是在浮点上。 Again you may find that using a double resolve the problem - especially as strictly that is the type expected by the %f format specifier in an ISO conforming implementation. 再次,您可能会发现使用double可以解决问题-尤其严格地说,这是%f格式说明符在符合ISO的实现中期望的类型。 As I said, you are probably best off avoiding floating point altogether on such a target. 就像我说的那样,您最好最好完全避免在这样的目标上出现浮点。

Note that if you are using Rabbit's Dynamic C compiler, you should be clear that Dynamic C is not an ISO conforming C compiler. 请注意,如果您使用的是Rabbit的Dynamic C编译器,则应该清楚Dynamic C不是符合ISO的C编译器。 It is a proprietary C-like language, that is similar enough to C to cause a great deal of confusion! 它是一种类似于C的专有语言, C 相似,足以引起很多混乱! Specifically it does not support double precision ( double ) floating point. 具体来说,它不支持双精度( double )浮点。

f1 += (1/3600); should be f1 += (1.0f/3600.0f); 应该是f1 += (1.0f/3600.0f); .

If you perform integer division then result will also be integer. 如果执行整数除法,则结果也将是整数。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM