浮点数

来源:互联网 发布:剑三南风成女捏脸数据 编辑:程序博客网 时间:2024/04/29 11:35
有关浮点数比较详细的解释请参考如下内容:(老外写的,需要翻墙,用到时再看即可)
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm (老版本)
http://randomascii.wordpress.com/2012/02/25/
comparing-floating-point-numbers-2012-edition/  (新版本需翻墙)
http://blog.csdn.net/quickbasic411/article/details/5921420 (老版本翻译板)

1
浮点数的存储格式基本采用的都是 IEEE754-1985 标准,此格式为
***************************************************
| sign(1bit) |  exponent(8bit) | mantissa(23bit)  |
***************************************************
sign符号位 (正为0,负为1)
exponent(8bit) 指数位,用移码表示,范围为 0~255
mantissa(23bit) 尾数位,用原码表示, 尾数位前面省略了1,代表1.XXXXX

2
把十进制数转化为二进制浮点数
如 5.2
首先把5转化为二进制 101
然后把 0.2转化为二进制,因为 0.2不能完全不损失的转化为二进制,因此
0.2转化为二进制后的数是不能完全还原成0.2的. 00110011001100...
则 5.2(10进制) =  101.00110011001100...(2进制)
进行移位,移成  1.0100110011001100 * 2^2
然后符号为 0, exponent为 2+ 127(移码表示), 尾数为 01001100110011(共23位)

3
把二进制转化为十进制
二进制转化为十进制过程中也会存在误差

4
探究程序

可以用以下程序进行探索:

typedef unsigned int uint32_t;typedef int int32_t;//联合体在C++中的使用//float f 和 int32_t i 共用内存//可以使用类的相关语法,类中的方法不占用内存空间(运行时占用,并于这方面的详细情况需要 《探索C++对象模型》)union Float_t{    Float_t(float num = 0.0f) : f(num) {}    bool Negative() const { return (i >> 31) != 0; }    int32_t RawMantissa() const { return i & ((1 << 23) - 1); }    int32_t RawExponent() const { return (i >> 23) & 0xFF; }     int32_t i;    float f;#ifdef _DEBUG    struct    {   // 有关bit field 可以参看另一篇博客<结构体位段>        uint32_t mantissa : 23;        uint32_t exponent : 8;        uint32_t sign : 1;    } parts;#endif};void TestFunction(){    Float_t num(1.0f);    printf("Float value, representation, sign, exponent, mantissa\n");    for (;;)    {        // 在这里打个断点,然后就可以在VC++中通过DEBUG进行调试//不断的改为 mantissa/exponent/sign的值可以查看 f和i的值(在DEBUG窗口中改)        printf("%1.8e, 0x%08X, %d, %d, 0x%06X\n",            num.f, num.i,            num.parts.sign, num.parts.exponent, num.parts.mantissa);    }}
5
当指数(移码 [x]移 = 2^n + x)为0 时代表浮点数 0;
当指数为255 时,如果尾数为0则为 NaN;如果尾数不为0,则为无效数.

假如是float型,则最大的符点数为:
sign 0
exponent 254 (移码)
mantissa 1.11111111... (这是二进制表示,转换为十进制,基本接近于2)
则大约为  2*2^127 = 3.4e+38

最小float型
sign 1
exponent 1 (移码)
mantissa 1.11111111... (这是二进制表示,转换为十进制,基本接近于2)

最小正数:
sign 0
exponent 1 (移码)
mantissa 1.000000... (这是二进制表示,转换为十进制,基本接近于2)

6 浮点数的比较
浮点数的比较有两种情况: 利用绝对误差或相对误差
如果已经知道两个需要比较数的数量级和允许的误差值则可以直接使用 绝对误差,如 fabs(a-b) <=

0.0001
如果上式成立则认为 a = b;

如果不知道需要比较数的数量级,则可以使用相对误差:

bool AlmostEqualRelative(float A, float B, float maxRelDiff){    // Calculate the difference.    float diff = fabs(A - B);    A = fabs(A);    B = fabs(B);    // Find the largest    float largest = (B > A) ? B : A;    //largest * maxRelDiff 使用允许的误差值在和数量级保持一致    if (diff <= largest * maxRelDiff)        return true;    return false;}
还有一种比较经典比较方法,使用和浮点数相关的整数进行比较,这时候
请参考:
http://www.cygnus-software.com/papers/comparingfloats/comparingfloats.htm
一个相关的翻译
http://blog.csdn.net/quickbasic411/article/details/5921420

7
浮点数的加减/乘除 过程中, 尾数(原码表示)是如何处理的,符号为是的如何处理的,未找到
相关介绍,暂定(所有教课书中介绍的都不是IEEE标准的浮点数,教课书中尾数都用补码表示)