amobbs.com 阿莫电子技术论坛

标题: 两个float数据相乘结果不对,需要加什么关键词转换? [打印本页]

作者: neutronlmk    时间: 2024-6-28 17:13
标题: 两个float数据相乘结果不对,需要加什么关键词转换?
数据类型:
  1. typedef enum
  2. {
  3.         QMA6100P_SENSITITY_2G = 244,
  4.         QMA6100P_SENSITITY_4G = 488,
  5.         QMA6100P_SENSITITY_8G = 977,
  6.         QMA6100P_SENSITITY_16G = 1950,
  7.         QMA6100P_SENSITITY_32G = 3910
  8. }qma6100p_sensitity;

  9. typedef struct {
  10.         int16_t temp;
  11.        
  12.         int16_t acc_x;
  13.         int16_t acc_y;
  14.         int16_t acc_z;
  15. }QMA6100PRawData_t;
复制代码


采集数据:
  1. void QMA6100PReadRawData(QMA6100PRawData_t *rawdata)
  2. {
  3.         int16_t  temp=0;

  4.         temp=(int16_t)(QMA6100P_Read(QMA6100P_REG_XOUTL)+(QMA6100P_Read(QMA6100P_REG_XOUTH)<<8));
  5.         rawdata->acc_x=temp>>2;
  6.    
  7.         temp=(int16_t)(QMA6100P_Read(QMA6100P_REG_YOUTL)+(QMA6100P_Read(QMA6100P_REG_YOUTH)<<8));
  8.         rawdata->acc_y=temp>>2;
  9.    
  10.         temp=(int16_t)(QMA6100P_Read(QMA6100P_REG_ZOUTL)+(QMA6100P_Read(QMA6100P_REG_ZOUTH)<<8));
  11.         rawdata->acc_z=temp>>2;
  12. }
复制代码


多个float 运算:
  1.     volatile QMA6100PRawData_t rawdata;
  2.     float x,y,z;
  3.    
  4.     QMA6100PReadRawData(&rawdata);

  5.     //x=(float)(rawdata.acc_x*QMA6100P_SENSITITY_8G)/1000.0;
  6.     //y=(float)(rawdata.acc_y*QMA6100P_SENSITITY_8G)/1000.0;
  7.     //z=(float)(rawdata.acc_z*QMA6100P_SENSITITY_8G)/1000.0;
  8.    
  9.     x=(float)(rawdata.acc_x)*0.977f;
  10.     y=(float)(rawdata.acc_y)*0.977f;
  11.     z=(float)(rawdata.acc_z)*0.977f;
  12.    
复制代码


把数据打印出来看 rawdata.acc_x、rawdata.acc_y、rawdata.acc_z采集回来数据都是对的。
注释掉的代码求出来的x、y、z结果都不对。

没注释的x、y、z运算结果是对的。

请教下注释掉的代码如何修改才能得到正确的x、y、z?

作者: amigenius    时间: 2024-6-28 17:21
不先强制转换成float,两个int16相乘会溢出,所以结果错误。写成以下任意一种均可:
x=((float)rawdata.acc_x*QMA6100P_SENSITITY_8G)/1000.0f;
y=((float)rawdata.acc_y*QMA6100P_SENSITITY_8G)/1000.0f;
z=((float)rawdata.acc_z*QMA6100P_SENSITITY_8G)/1000.0f;

或:

x=(rawdata.acc_x*(float)QMA6100P_SENSITITY_8G)/1000.0f;
y=(rawdata.acc_y*(float)QMA6100P_SENSITITY_8G)/1000.0f;
z=(rawdata.acc_z*(float)QMA6100P_SENSITITY_8G)/1000.0f;
作者: at90s    时间: 2024-6-28 17:22
x=((float)rawdata.acc_x*QMA6100P_SENSITITY_8G)/1000.0;
作者: PPS    时间: 2024-6-28 17:25
看看是不是溢出了,先转换成double再计算试试
作者: jadegu    时间: 2024-6-28 17:30
16位运算出来的结果,不能放进32位的数据类型吧,不报warning吗
作者: neutronlmk    时间: 2024-6-28 17:43
amigenius 发表于 2024-6-28 17:21
不先强制转换成float,两个int16相乘会溢出,所以结果错误。写成以下任意一种均可:
x=((float)rawdata.acc ...
(引用自2楼)

是不是arm系列芯片不用这样处理?
作者: yuyu87    时间: 2024-6-28 19:20
neutronlmk 发表于 2024-6-28 17:43
是不是arm系列芯片不用这样处理?
(引用自6楼)

与ARM无关,C语言都用的一个标准。
作者: neutronlmk    时间: 2024-6-28 20:31
再来一段求加速度的运算:
  1. g=sqrt(x*x+y*y+z*z);
复制代码

也是没得到正确的g
作者: tomzbj    时间: 2024-6-29 20:29
溢出了? 8位或者16位平台? 前面的enum改成这样试试?

  1. #define QMA6100P_SENSITITY_2G  244UL
  2. #define QMA6100P_SENSITITY_4G  488UL
  3. #define QMA6100P_SENSITITY_8G  977UL
  4. #define QMA6100P_SENSITITY_16G  1950UL
  5. #define QMA6100P_SENSITITY_32G  3910UL
复制代码

作者: neutronlmk    时间: 2024-6-30 21:30
tomzbj 发表于 2024-6-29 20:29
溢出了? 8位或者16位平台? 前面的enum改成这样试试?
(引用自9楼)

是用了8位平台,感谢。
想起了ul这关键词
作者: tomzbj    时间: 2024-7-1 08:55
neutronlmk 发表于 2024-6-30 21:30
是用了8位平台,感谢。
想起了ul这关键词
(引用自10楼)


又查了一下, 没准编译器支持这样操作, enum里增加一个手工指定为超过int范围的数, 就都是long了.
你试试把enum改成这样:
typedef enum
{
        QMA6100P_SENSITITY_2G = 244,
        QMA6100P_SENSITITY_4G = 488,
        QMA6100P_SENSITITY_8G = 977,
        QMA6100P_SENSITITY_16G = 1950,
        QMA6100P_SENSITITY_32G = 3910,
        QMA6100P_SENSITITY_MAX = 0x40000ul
}qma6100p_sensitity;

然后sizeof一下看看, 是2还是4?




欢迎光临 amobbs.com 阿莫电子技术论坛 (https://www.amobbs.com/) Powered by Discuz! X3.4