定点数数学例程



Allegro 提供了一些例程支持定点运算, 并将类型 'fixed' 定义成一个32位的整数. 高位字用来做整数部分, 低位字用来做小数部分. 这样就提供了一个范围在 -32768 至 32767, 有 4 到 5个小数点精度的定点数. 定点数可用普通的整数操作 来赋值, 比较大小, 相加, 相减, 取负, 和位移 (用来乘或除 2 的次方数) 但当用户将定点数与整型数和浮点数进行运算时需注意要使用合适的类型转换例程.

'fixed_point_1 + fixed_point_2' 这样写是对的, 但是 'fixed_point + integer' 是错的.

fixed itofix(int x);
将一个整数转换成定点数.

int fixtoi(fixed x);
将一个定点数转换成整型数. 如果你想避免四舍五入, 就改用 x>>16.

fixed ftofix(float x);
将一个浮点数转换成定点数.

float fixtof(fixed x);
将一个定点数转换成浮点数.

fixed fmul(fixed x, fixed y);
一个定点数可通过 '*' 和 '/' 运算符与一个整型数进行乘或除运算. 但用户必须使用该函数将两个定点数相乘.


如果出现溢出或被 0 除, errno 将被设置成可能返回的最大值, 但是 errno 不会在下一次该函数被正确调用后被自动清零. 这就是说如果用户想检测溢出的话, 必须在调用 fmul() 之前将 errno 设置成0.  

fixed fdiv(fixed x, fixed y);
定点数相除, 详见 fmul().

fixed fadd(fixed x, fixed y);
尽管定点数可通过 '+' 运算符相加, 但其不能对溢出进行保护. 如果用户关心溢出的话, 则需使用该函数. 它比直接使用整数操作要慢, 但当溢出出现时它将夹住结果, 设置 errno, 而不是将其值翻转.

 

fixed fsub(fixed x, fixed y);
定点数相减, 详见 fadd().

定点数平方, sin, cos, tan, arc sin, 和 arc cos 是通过查询表来实现的, 所以他们很快, 但不是十分准确. 当前 arc tan 是通过迭代法来查找该表的, 所以它比其他都慢许多.


Allegro 将 360 度分成 256 等份, 64 代表一个直角. 这样只需使用位与运算就可使一个角度保持在 0 到 360度之间, 可免去繁复的 '分(angle >= 360)' 检测.

  fixed fsin(fixed x);
查询 sin 函数表.

fixed fcos(fixed x);
查询 cos 函数表.

fixed ftan(fixed x);
查询 tan 函数表.

fixed fasin(fixed x);
查询 arc sin 函数表.

fixed facos(fixed x);
查询 arc cos 函数表.

fixed fatan(fixed x);
定点反正切

fixed fatan2(fixed y, fixed x);
libc atan2() 例程的定点版本.

fixed fsqrt(fixed x);
定点平方根.

 


如果用户使用的是 C++ 则可使用定点类而不是以上介绍的函数. 定点类重载了许多运算符用 来实现整型数和浮点数之间的转换, 并且需要时调用前面介绍的函数.用户不可将 定点类和 定点 typedef 混用, 这是因为编译器将把定点数当成一般的整型数, 而进行不必要的类型转换. 举例来说, 如果 x 是应该定点类型的对象, 调用 fsqrt(x) 会返回一个错误的结果. 用户应该调用重载的 sqrt(x) 或 x.sqrt().





返回