关于STM32 double类型数据计算

本文记录了一段代码在PC上运行正常,但在STM32上出现计算误差的问题。作者逐步排查,怀疑是double类型精度问题及pow函数在MCU中的实现导致的误差。通过将pow运算分解为多次乘法,最终解决了计算错误,验证了MCU进行大数值计算时应避免复杂运算并分步进行。
摘要由CSDN通过智能技术生成

double PresetFlow2PVavleDuty(float presetflow)
{
    double n[8] = {
        49.2335778711886,      // a  0
        55.9585083556069,      // b  1
        -13.5915770179714,     // c  2
        1.54143446997669,      // d  3
        -0.0897576896073748,   // e  4
        0.00281694608223768,   // f  5
        -4.53186805980947E-05,  // g  6
        2.93852523414571E-07,   // h  7
    };

    float x = presetflow;
    double duty = 0;

    float x = presetflow;
    double duty =(n[7]*pow(x, 7) + n[6]*pow(x, 6) + n[5]*pow(x, 5) + n[4]*pow(x, 4) + n[3]*pow(x, 3) + n[2]*pow(x, 2) + n[1]*x + n[0]);
    return duty;
}

 同样的上面一段代码,在PC上测试计算完全没问题,在STM32上计算就出现大问题,用12实参传入计算得到结果是七十多万。。。。正确应该是140多。

难道STM32不支持double?

猜测可能最后一步计算太大导致计算有误,遂改为如下:

double PresetFlow2PVavleDuty(float presetflow)
{
    double n[8] = {
        49.2335778711886,      // a  0
        55.9585083556069,      // b  1
        -13.5915770179714,     // c  2
        1.54143446997669,      // d  3
        -0.0897576896073748,   // e  4
        0.00281694608223768,   // f  5
        -4.53186805980947E-05,  // g  6
        2.93852523414571E-07,   // h  7
    };

    float x = presetflow;
    double duty = 0;
    char i;

    double result[7];

    result[0] = n[1]*x;
    result[1] = n[2]*pow(x, 2);
    result[2] = n[3]*pow(x, 3);
    result[3] = n[4]*pow(x, 4);
    result[4] = n[5]*pow(x, 5);
    result[5] = n[6]*pow(x, 6);
    result[6] = n[7]*pow(x, 7);

    for (i = 0; i < 7; i++)
    {
        duty += result[i];
    }

    duty += n[0];

    return duty;
}

结果同样是PC上正确,STM32上就错了。

接着修改为:

double PresetFlow2PVavleDuty(float presetflow)
{
    double n[8] = {
        49.2335778711886,      // a  0
        55.9585083556069,      // b  1
        -13.5915770179714,     // c  2
        1.54143446997669,      // d  3
        -0.0897576896073748,   // e  4
        0.00281694608223768,   // f  5
        -4.53186805980947E-05,  // g  6
        2.93852523414571E-07,   // h  7
    };

    double duty = 0;
    float x = presetflow;

    double x2 = pow(x, 2);
    double x3 = pow(x, 3);
    double x4 = pow(x, 4);
    double x5 = pow(x, 5);
    double x6 = pow(x, 6);
    double x7 = pow(x, 7);

    double result[7];

    result[0] = n[1]*x;
    result[1] = n[2]*x2;
    result[2] = n[3]*x3;
    result[3] = n[4]*x4;
    result[4] = n[5]*x5;
    result[5] = n[6]*x6;
    result[6] = n[7]*x7;

    for (char i = 0; i < 7; i++)
    {
        duty += result[i];
    }
 
    duty += n[0];
    return duty;
}

 计算结果还是错误的。

难道是pow函数的锅?

进一步修改:

double PresetFlow2PVavleDuty(float presetflow)
{
    double n[8] = {
        49.2335778711886,      // a  0
        55.9585083556069,      // b  1
        -13.5915770179714,     // c  2
        1.54143446997669,      // d  3
        -0.0897576896073748,   // e  4
        0.00281694608223768,   // f  5
        -4.53186805980947E-05,  // g  6
        2.93852523414571E-07,   // h  7
    };

    double duty = 0;
    float x = presetflow;
    float x2 = x * x;
    float x3 = x2 * x;
    float x4 = x3 * x;
    float x5 = x4 * x;
    float x6 = x5 * x;
    float x7 = x6 * x;

    double result[7];

    result[0] = n[1]*x;
    result[1] = n[2]*x2;
    result[2] = n[3]*x3;
    result[3] = n[4]*x4;
    result[4] = n[5]*x5;
    result[5] = n[6]*x6;
    result[6] = n[7]*x7;

    for (char i = 0; i < 7; i++)
    {
        duty += result[i];
    }
    
    duty += n[0];
    return duty;
}

结果正确了。。。

不知道是不是pow函数的锅,还有MCU做大数值计算最好还是得分步计算

  • 4
    点赞
  • 4
    收藏
    觉得还不错? 一键收藏
  • 打赏
    打赏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包

打赏作者

欲盖弥彰1314

你的鼓励将是我创作的最大动力

¥1 ¥2 ¥4 ¥6 ¥10 ¥20
扫码支付:¥1
获取中
扫码支付

您的余额不足,请更换扫码支付或充值

打赏作者

实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值