• 定点数的表示


    定点数的表示

    所有的定点数学实际上是以整数尺度为基础的。比如,我们想用一个整数来表示10.5。这做不到,因为没有小数位。你可以将其截断为10.0或将其舍入为11.0,但10.5不是一个整数。但如果你将10.5放大10倍,10.5就变成了105.0,这是一个整数。这便是定点数的基础。你可以采用某一比例系数来对数值进行缩放,并在进行数学计算时将比例系数考虑进去。

    由于计算机是二进制的,大部分游戏程序倾向于使用32位整数(或int),以16.16的格式来表示定点数。


    你可以将整数部分放在高16位,小数部分置于低16位。这样你已将整个数值放大为原来的2^16即65536倍。另外,为提取出一个定点数的整数部分,你可以移位并屏蔽掉高16位;为得到小数部分,你可以移位并屏蔽掉低16位。

    以下是一些常用的定点数的类型:

    #define FP_SHIFT 16 // shifts to produce a fixed-point number

    #define FP_SCALE 65536 // scaling factor

    typedef int FIXPOINT;

    在定点与浮点之间转换

    有两类数需要转换为定点数:整数和浮点数。这两类转换是不同的,需分别考虑。对于整数,直接用其二进制的补码表示。所以你可以移位操作来放大这个数,从而将其转换为定点数。而对于浮点数,由于其使用IEEE格式,四字节中有一个尾数和指数,因此移位将破坏这个数。因此,必须使用标准的浮点乘法来进行转换。

    数学

    二进制补码是一种表示二进制整数的方法。因此整数和负数均可以用这种方法表示,并且在该集合上数学运算都是正确的。一个二进制数的补码是指将该二进制的每一位取反并与1进行加运算所得的数。在数学意义上,假定你想求6的补码,先取反码得-6,再与1相加即-6+1或~0110+0001=1001+0001=1010。该数就是10的普通二进制表示,但同时也是-6的补码表示。

    以下是将整数转换为定点数的宏:

    #define INT_TO_FIXP(n) (FIXPOINT((n << FP_SHIFT)))

    例如:

    FIXPOINT speed = INT_TO_FIXP(100);

    下面是将浮点数转换为定点数的宏:

    #define FLOAT_TO_FIXP(n) (FIXPOINT((float)n * FP_SCALE))

    例如:

    FIXPOINT speed = FLOAT_TO_FIXP(100.5);

    提取一个定点数也很简单。下面是从高16位提取整数部分的宏:

    #define FIXP_INT_PART(n) (n >> 16)

    至于从低16位提取小数部分,则只需将整数部分屏蔽掉即可:

    #define FIXP_DEC_PART(n) (n & 0x0000ffff)

    当然,如果你聪明的话,可以不需要进行转换,只要使用指针即时地访问高16位和低16位即可。如下所示:

    FIXPOINT fp;

    short *integral_part = &(fp+2), *decimal_part = &fp;

    指针integral_part和decimal_part总是指向你所需的16位数。

  • 相关阅读:
    js 数组去重求和 (转载)
    表格插件汇总(转载)
    SQL Server 用一张表的数据更新另一张表的数据(转载)
    C#创建DataTable(转载)
    C# DataTable 和List之间相互转换的方法(转载)
    维度表,实体表,事实表之间的关系
    Scala中foldLeft的总结
    Scala集合Map
    从合并两个Map说开去
    UDAF(用户自定义聚合函数)求众数
  • 原文地址:https://www.cnblogs.com/siceblue/p/2597694.html
Copyright © 2020-2023  润新知