C方程返回的值与我的计算值不同

C方程返回的值与我的计算值不同,c,C,我用这个方程来解温度传感器的温度 变量包括: unsigned char AD_DATA; values is usually 100- 110; int TEMP; 原始方程式: TEMP = 50 - (AD_DATA * 175) / 1000; 我改为: TEMP = 500 - (AD_DATA * 1750) / 1000; 这是因为TEMP是一个整数,因此在第一个方程中,当计算出有一个小数点时,它会自动四舍五入,所以我修改了它,使小数点包含在数字中 我不使用float的原因是

我用这个方程来解温度传感器的温度

变量包括:

unsigned char AD_DATA; values is usually 100- 110;
int TEMP;
原始方程式:

TEMP = 50 - (AD_DATA * 175) / 1000;
我改为:

TEMP = 500 - (AD_DATA * 1750) / 1000;
这是因为TEMP是一个整数,因此在第一个方程中,当计算出有一个小数点时,它会自动四舍五入,所以我修改了它,使小数点包含在数字中

我不使用float的原因是,在我使用的MCU中,每当我在ISR(中断服务例程)中声明一个float变量时,它都会返回一个错误,因此我需要创造性地只使用INT,double也会返回一个错误

现在使用的AD_数据值为100

第一个方程式的结果是:32.5,但由于它是整数,现在是33

第二个等式应该输出325,但在我的输出中是521

我需要在我的显示中包含小数点,因此将其包含在等式中非常重要

我的ISR例行程序:

__interrupt void ADC_int(void){
IO_ADCSH.bit.INT = 0;
AD_DATA = IO_ADCRLH.DATA8;
TEMP = 500 - (AD_DATA * 1750) / 1000;
}
微控制器规格

int 2bytes
long 4bytes
unsigned char 1byte

我的第一个猜测是根据你提供的信息, 寄存器长度为16位,导致AD_数据乘以1000时操作数溢出

一个int可以保存的最大值是32762(从我的头顶开始,更像0x7FFF),即使没有符号,它也不足以保存AD_数据*1000(在你的例子中是18*1000=18000),该值将被截断为16位,在这个过程中给出一个负数


您可以通过在表达式中指定运算符的长度并将AD_数据强制转换为32位字来修复此问题。

作为一种快速破解方法,您可以将
(AD_数据*1750)/1000
替换为
(AD_数据*7)/4

欲知更多想法,请阅读下文


注意,通过改变

TEMP = 50 - (AD_DATA * 175) / 1000;

您更改了
TEMP
变量的含义。假设它的意思是“温度”(其实并不重要),它的意思是“以度为单位的温度”,现在它的意思是“以1/10度为单位的温度”。但是,你为什么要乘以10?只是为了方便起见,我想-你不必为你的单位使用10的幂。您可以使用任何其他数字,只要您记得它是什么,并相应地处理结果
TEMP
(例如,打印时将其除以10)。因此,最好使用的数字是40:它消除了除法(或者更确切地说,延迟到后面的代码行),从而避免了精度损失

TEMP_MULTIPLIED_BY_40 = 2000 - AD_DATA * 7;

mcu规格是什么,特别是寄存器位length@dvhh更新了问题
无符号int
的最大值为65535,但
100*1750
为175000,因此存在溢出。更好的是,存在未定义的行为。使用一个更大的整数,比如AD_数据,你的问题就解决了。是的,在一个4字节整数的处理器上运行,我得到了325。我得到了一些负数,我尝试使用long,但它仍然返回519而不是325,我仍然不能在中断例程中使用double或float在long first中存储AD_数据,也不能在long first中将其转换为longexpression@magicianIam无需将
AD_数据存储/转换为
long
。只要乘以一个
long
常量。@chux把它乘以一个长常量是什么意思?@magiciam关于“错误”的信息很重要;你应该将错误信息粘贴到你的问题中。当你忘记分数的那一刻,感谢你提供了这个干净的解决方案。我应该更清楚:)
TEMP_MULTIPLIED_BY_40 = 2000 - AD_DATA * 7;