本文是其中的一部分嵌入式软件系列:ADA为嵌入式C开发人员
许多数值应用程序通常使用浮点类型来计算值。然而,在一些平台中,可能无法使用浮点单元。其他平台可能具有浮点单元,但在某些数值算法中的使用可能在性能方面是持久的。对于这些情况,定点算术可能是一个很好的替代方案。
在查看此代码片段时,固定点和浮点类型之间的差异可能是如此明显:
- fixed_definitions.ads包固定_definitions是d:常量:= 2.0 **(-31);类型固定为Delta D范围-1.0 .. 1.0 - D;结束固定_definitions;- show_float_and_fixed_point.adb与ada.text_io;使用ada.text_io;用固定_definitions;使用fixed_definitions;过程show_float_and_fixed_point是float_value:float:= 0.25;fixed_value:固定:= 0.25;begin float_value:= float_value + 0.25; Fixed_Value := Fixed_Value + 0.25; Put_Line (“Float_Value = “ & Float’Image (Float_Value)); Put_Line (“Fixed_Value = “ & Fixed’Image (Fixed_Value)); end Show_Float_And_Fixed_Point;在此示例中,应用程序将显示float_value和fixed_value的值0.5。
浮点和定点类型之间的主要区别在于存储值的方式。实际上,普通固定点类型的值缩放整数。用于普通固定点类型的缩放由类型的小(比例因子)定义,该类型来自指定的增量,默认情况下是两个的功率。
因此,普通的定点类型有时被称为二进制固定点类型。从这种意义上讲,可以认为普通的定点类型靠近机器上的实际表示。实际上,普通的定点类型可以使用可用的整数换档指令。
浮点和定点类型之间的另一个差异是ADA不提供标准的定点类型 - 除了持续时间类型,用于表示在秒内的时间间隔。虽然ADA标准指定浮点类型,如float和long_float,但我们必须声明自己的定点类型。请注意,在前面的示例中,我们使用命名为“修复:”的固定点类型。此类型不是标准的一部分,但必须在我们应用程序的源代码中声明它。
普通固定点类型的语法是:
type(type_name)是delta(delta_value)范围(depart_bound)..(Upper_bound);
默认情况下,编译器将选择比例因子或小型,这是2的功率超过
例如,我们可以在-1.0和1.0之间定义归一化范围,如下所示:
- 具有ada.text_io的Irandalized_fixed_point_type.adb;使用ada.text_io;过程归一化_fixed_point_type是d:常量:= 2.0 **(-31);TQ31型是Delta D范围-1.0 .. 1.0 - D;begin Put_Line ("TQ31 requires " & Integer’Image (TQ31’Size & " bits"); Put_Line ("The delta value of TQ31 is " & TQ31'Image (TQ31'Delta)); Put_Line ("The minimum value of TQ31 is " & TQ31'Image (TQ31'First)); Put_Line ("The maximum value of TQ31 is " & TQ31'Image (TQ31'Last)); end Normalized_Fixed_Point_Type;
输出是:
TQ31需要32位TQ31的Δ值为0.000000000005 TQ31的最小值为0.0000000000,TQ31的最大值为0.9999999995在此示例中,我们为归一化范围定义了32位固定点数据类型。运行应用程序时,我们会注意到上限接近一个,但不是完全的。这是固定点数据类型的典型效果 - 您可以在此讨论中找到更多详细信息,了解Q格式。
在C的情况下,由于语言不支持定点算术,我们需要使用整数类型和通过函数进行自定义操作来模拟它。让我们来看看这个非常基本的例子:
- main.clude(stdio.h)#include(math.h)#define shift_factor 32 #define to_fixed(x)((int)((x)* pow(2.0,shift_factor - 1)))#defineto_float(x)((float)((double)(x)*(双)pow(2.0, - (shift_fact_factor-1))))Typedef int固定;固定添加(固定A,固定B){返回A + B;固定Mult(固定A,固定B){返回(固定)(((长)a *(long)b)>>(sift_factor - 1));void display_fixed(固定x){printf(“值(整数)=%d \ n”,x);printf(“值(float)=%3.5f \ n \ n”,to_float(x));} int main(int argc,const char * argv []){int fixed_value = to_fixed(0.25);printf(“原始值\ n”);display_fixed(fixed_value);printf(“... + 0.25 \ n”); fixed_value = add(fixed_value, TO_FIXED(0.25)); display_fixed(fixed_value); printf("... + 0.5\n"); fixed_value = add(fixed_value, TO_FIXED(0.5)); display_fixed(fixed_value); return 0; }
在这里,我们声明了固定点类型基于INT和IT的两个操作来固定:添加(通过ADD功能)和乘法(通过MULL函数)。请注意,虽然固定点添加非常简单,乘法需要右移以匹配正确的内部表示。在ADA中,由于定点操作是语言规范的一部分,因此不需要模仿它们。因此,程序员不需要额外的努力。
另请注意,上面的示例非常基本,因此它不会考虑定点算术的一些副作用。在C中,您必须手动考虑从固定点算术的所有副作用,而在ADA中,编译器负责为您选择合适的操作。
从中阅读更多嵌入式软件系列:ADA为嵌入式C开发人员