C 数学运算时如何强制编译器将变量提升为浮点

C 数学运算时如何强制编译器将变量提升为浮点,c,math,C,Math,我有一个关于C语言数学的问题,下面是一个简单的例子: uint32_t desired_val; uint16_t target_us=1500 uint32_t period_us=20000; uint32_t tempmod=37500; desired_val = (((target_us)/period_us) * tempmod); 此时(target_us/period_us)的结果为0,这也给出了所需的_值0。我不想让这些变量浮动,除非我真的必须这样做。我不需要逗号后的任何

我有一个关于C语言数学的问题,下面是一个简单的例子:

uint32_t desired_val;
uint16_t target_us=1500
uint32_t period_us=20000;
uint32_t tempmod=37500;


desired_val = (((target_us)/period_us) * tempmod);
此时(target_us/period_us)的结果为0,这也给出了所需的_值0。我不想让这些变量浮动,除非我真的必须这样做。我不需要逗号后的任何东西,因为它将被保存到32位寄存器

在不将目标值或周期值声明为浮动的情况下,是否可以从该等式中获得正确的结果?我想在可能的时候进行定点计算,在需要的时候进行浮点计算


在cortex-M4上工作,如果有帮助的话。

在任何情况下,你都可能需要进行一些铸造,但有两种不同的方法。首先,坚持使用整数并首先进行乘法:

desired_val = ((uint64_t)target_us * tempmod) / period_us;
或者使用浮点进行计算:

desired_val = (uint32_t)(((double)target_us / period_us) * tempmod);

先做乘法运算

您应该使用一个临时变量将其拆分为两个语句,以确保所需的操作顺序(括号确保正确分组,但不确保顺序)


我还使用了
uint64\u t
作为临时选项,以防产品溢出。如果所需的值不适合32位,则仍然存在问题;希望数据排除了这一点。

您可以非常轻松地使用
double
进行计算:

desired_val = (double)target_us  * tempmod / period_us;
float
将是一个错误,因为它的精度太低,不可靠

您可能希望将其舍入到最接近的整数,而不是让它被截断:

#include <math.h>
desired_val = round((double)target_us  * tempmod / period_us);
#包括
期望值=四舍五入((双)目标值*tempmod/周期值);


当然,您可以使用更宽的整数类型进行计算(例如,将
double
替换为
int64\t
long
)。这将使舍入稍微困难一些。

如果需要,先进行乘法运算,然后使用更大的数据类型
target\u us*tempmod/period\u us
@WeatherVane我认为这并不能保证特定的操作顺序。括号只是覆盖了运算符优先级。@jean François:由于C要求对乘法运算符进行左关联求值,因此您的表达式和weather的表达式保证产生相同的结果。@barmar:关联性是运算符优先级的一部分。@barmar运算符
*
/
具有相同的优先级,但是从左到右的关联性。因此
3/4*5
将给出
0
,但
3*5/4
将给出
3
。make
tempprod
a
uint64\u t
。给定target&tempmod的数据类型,否则可能会溢出。并将其中一个操作数也强制转换为64位。我会做
uint64_t tempprod=(uint64_t)target_us*tempmod
谢谢,我修正了这个问题,并添加了一个警告,如果最终结果不合适。请您详细说明“括号确保正确分组,但不是顺序”好吗?我一直认为当我写
(a*b)/c
时,
a*b
会首先被计算出来。或者优化器可以自由地重新安排吗?还有其他事情吗?@Arkadiy是的,优化器可以重新排列它,只要它在数学上是等价的。即使除法是在32位,乘法是在64位?他的CPU没有双重支持的FPU硬件。这就变成了软件仿真。
#include <math.h>
desired_val = round((double)target_us  * tempmod / period_us);