C:表示没有浮点数的分数

C: Representing a fraction without floating points

我正在为没有硬件浮点支持的嵌入式系统 (MSP430) 编写一些代码。不幸的是,在进行测距时,我需要在代码中使用分数,而精度为 1 米的短程传感器并不是一个很好的传感器。

我可以在整数中做尽可能多的数学运算,但到最后有两个值我肯定需要分数;范围和速度。范围将是 2-500 (cm) 之间的值,而速度不应高于 -10 到 10 (ms^-1)。如果可能的话,我不确定如何在没有浮点值的情况下表示它们。将分数四舍五入的简单方法是最好的。

我有一些示例代码:

voltage_difference_new = ((memval3_new - memval4_new)*3.3/4096); 其中 memval3_new 和 memval4_new 是整数,但 voltage_difference_new 是浮点数。

如果需要更多信息,请告诉我。或者如果有一个非常简单的修复方法。

您已经用以下陈述回答了您自己的问题:

Range will be a value between 2-500 (cm),

以厘米(甚至毫米)而不是米为单位工作。

那是说您不需要 floating-point 硬件来进行浮点运算;编译器将支持 "soft" 浮点并生成执行浮点运算的代码 - 它会比硬件浮点或整数运算慢,但这可能不是您的问题申请。

尽管如此,即使有硬件支持,也有很多理由要避免 floating-point,而且您的 FP 案例听起来并不特别引人注目,但如果不看您的代码和具体示例就很难判断。在 32 年的嵌入式系统开发中,即使是三角、对数、平方和数字信号处理,我也很少使用 FP。

一般的方法是使用定点演示。我之前使用厘米的建议是 十进制定点 的示例,但为了提高效率,您应该使用 二进制定点。例如,您可能以 1/1024 米为单位表示距离(精度 > 1 毫米)。因为固定点是二进制的,所以所有必要的重新缩放都可以通过移位而不是更昂贵的 multiply/divide 操作来完成。

例如,假设您有一个 8 位传感器生成 0 到 255 的线性输出,对应于 0 到 0.5 米的实际距离。

#define Q10_SHIFT = 10 ; // 10 bits fractional (1/1024)
typedef int q10_t ;

#define ONE_METRE = (1 << Q10_SHIFT)
#define SENSOR_MAX = 255
#define RANGE_MAX = (ONE_METRE/2)

q10_t distance = read_sensor() * RANGE_MAX / SENSOR_MAX ;

distance是Q10定点表示法。对这些进行加法和减法是正常的整数运算,乘法和除法需要缩放:

int q10_add( q10_t a, q10_t b )
{
    return a + b ;
}

int q10_sub( q10_t a, q10_t b )
{
    return a - b ;
}

int q10_mul( q10_t a, q10_t b )
{
    return (a * b) >> Q10_SHIFT ;
}

int q10_div( q10_t a, q10_t b )
{
    return (a << Q10_SHIFT) / b ;
}

当然,您可能希望能够混合类型,比如将 q10_t 乘以 int - 为 fixed-point 提供综合库可能会变得复杂。为此,我个人使用 C++,其中有 类、函数重载和运算符重载以支持更自然的代码。但是除非你的代码有大量的通用定点数学,否则编写特定的定点运算可能会更简单 ad-hoc.

以您提供的一个例子为例:

double voltage_difference_new = ((memval3_new - memval4_new)*3.3/4096);

那里的 floating-point 使用毫伏被简单地删除了:

int voltage_difference_new_mv = ((memval3_new - memval4_new) * 3300) /4096 ;

问题可能会成为陈述之一。例如,如果您必须向用户显示或报告 volts 中的值。在那种情况下:

int volt_fract = abs(voltage_difference_new_mv % 1000) ;
int volt_whole = voltage_difference_new_mv / 1000 ;
printf( "%d.%04d", volt_whole, volt_fract ) ;