IEEE-754浮点标准简介

IEEE-754浮点标准[1]

直至20世纪70年代末, 实数(十进制数)被不同的计算机厂商表示成不同的二进制形式, 这使得许多程序与不同的机器不兼容. 1980年IEEE委员会将实数的浮点数据表示进行了标准化. 该标准大部分由Intel基于8087数学协处理器定制的. 认识到不同的程序需要不同的精度, 因此建立了单精度和双精度. 而今几乎所有的软件和硬件公司都遵循这些标准, 因此有必要做一些了解.

IEEE-754单精度浮点数

IEEE单精度浮点数使用32位数据表示\displaystyle 2^{128}\displaystyle 2^{-126}范围内的正负实数. 转换为十进制大约是\displaystyle 1.2^{-38}\displaystyle 3.4^{+38}的正负实数. 这种单精度浮点数有时也叫短实数. 32位单精度形式的赋值如下图所示:

i3e-single-precision-floating-point-numbers.png

为了数学处理器的硬件设计更简单以及更少的晶体管消耗, 指数部分被加上一个常数\displaystyle \text{0x7F}(127_{10})作为偏置指数. 从实数转换为浮点有以下步骤:

  1. 实数转换为二进制形式.

  2. 科学计数法表示二进制: 1.xxx E yyy (\displaystyle {1.xxx} \times 2^{yyy}).

  3. 第31位填充0(正数)或1(负数).

  4. 指数部分, yyy加上0x7F作为偏置指数, 填充第30~23位.

  5. 有效数字部分填充第22~0位.

例子

例1: 将\displaystyle 9.75_{10}转换成单精度(短实数)浮点.

\displaystyle 9.75_{10} = \displaystyle 1001.11_2 = 二进制科学计数法 1.00111 E 3

正数b31 = 0

偏置指数b30-23为1000 0010(3+7F=82H)

有效数字位b22-0为 001110000000000000000…00.

综合给出二进制形式, 下面一行是16进制值

0100 0001 0001 1100 0000 0000 0000 0000
4    1    1    C    0    0    0    0

例2: Convert decimal 15.575 to IEEE single-precision standard.

化成二进制形式
    15 = 0xF = 0b1111
    0.575 * 2 = 1.15    1
    0.15  * 2 = 0.3     0
    0.3 * 2 = 0.6       0

    0.6 * 2 = 1.2       1
    0.2 * 2 = 0.4       0
    0.4*2 = 0.8         0
    0.8*0.2 = 1.6       1

    15.575 = 1111.100 1001 1001... = 1.111 1001 0011 0011 E 3
指数: 3+0x7F = 0x82 = 1000 0010
浮点: 0100 0001 0111 1001 0011 0011... = 0x41793333

例3: Convert decimal –0.00075 to IEEE single-precision standard.

使用16进制转换为二进制形式
    0.00075 * 16 = 0.012    0
                 = 0.192    0
                 = 3.072    3
                 = 1.152    1
                 = 2.432    2
                 = 6.912    6
                 = 14.592   E
                 = 9.472    9
                 = 7.552    7
二进制形式: 0.00075 = 0x0.3126E97 E -2= 0b 1.1000100100110111010010111 E -11
指数: -0xB+0x7F = 0x74 = 0b 0111 0100
浮点: 1011 1010 0100 0100 1001 1011 1010 0110 = 0xBA449BA6

验证程序(c):

  • c版本

    float x = -0.00075f;
    printf("0x%X\n", *(int*)&x);
    int y = 0xBA449BA6;
    printf("%f\n", *(float*)&y);
    
  • java版本

    float x = -0.00075f;
    System.out.println(Integer.toHexString(Float.floatToIntBits(x)).toUpperCase());
    

应用

  1. libminecraftpe.so某个函数的反汇编

    ; _DWORD ExperiencePotion::getThrowPower(ExperiencePotion *__hidden this)
                    EXPORT _ZN16ExperiencePotion13getThrowPowerEv
                    MOV.W           R0, #0x3F000000
                    BX              LR
    

    我们来算一下这个浮点值(怎么确定这是个浮点?):

    0x3F000000 = 0b 0011 1111 0000 ...0000
    b31=0, 正数
    指数: 0b011 1111 0 = 7E, 7E-7F=-1
    有效数字:0
    结果: 1.0 E -1(二进制) = 0.5(十进制)
    
  2. 下面代码的输出结果

    float a = 0x7FFFFFFF;
    float b = 0x7FFFFFFE;
    System.out.println(a == b);
    

    对于float类型加1不会产生任何影响的最小数是\displaystyle 2^{25} = 33,554,432, 而对于 double 类型最小 数是 \displaystyle 2^{54} \approx 1.8 × 10^{16}. 相邻的浮点数值之间的距离被称为一个ulp[3], 它是"最小单位 (unit in the last
    place)"的缩写. java中引入了Math.ulp方法来计算float或 double数值的ulp。

    例如, ulp(1.0f)=1.19xxE-7, ulp(0x7FFFFFC0) = 128.0, 于是(float)0x7FFFFFC0 = 0x7FFFFFFF.

  3. 是否存在一个数a使得:a==a+1 && a==a+2为true?

  4. 是否存在a,使得 a != a ?

  5. 是否存在a,使得 a != a+0 ?

  6. 下面代码输出结果什么?

    int start = 2_0000_0000;
    int count = 0;
    for (float f = start; f < start+20; f++){
        count++;
    }
    System.out.println(count);
    

IEEE-754双精度浮点数

双精度浮点数(Intel称之为长实数)可以表示\displaystyle 2.3^{-308}\displaystyle 1.7^{+308}的正负实数. 52位有效数字, 11位指数, 第63位表示符号. 转换过程和单精度浮点一样, 首先表成1.xxx E yyy, 然后yyy加3FF得到偏置指数. 如下图所示:

i3e-double-precision-floating-point-numbers.png

例4: Convert decimal 152.1875 to double-precision FP.

152.1875 = 二进制10011000.0011 = 科学二进制1.00110000011 E 7

b63 = 0

偏置指数b62-53 = 10000000110 (7+3FF=406)

有效数字位b52-0 = 00110000011000…..000

0100 0000 0110 0011 0000 0110 0000 0000 0000 ...  0000
4    0    6    3    0    6    0    0    0    ...  0

参考资料

[1]. Muhammad Ali Mazidi etc. ARM Assembly Language Programming & Architecture [M]. section5.3

[2].IEEE_754

[3].Unit in the last place

©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 204,590评论 6 478
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 86,808评论 2 381
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 151,151评论 0 337
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 54,779评论 1 277
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 63,773评论 5 367
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 48,656评论 1 281
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 38,022评论 3 398
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 36,678评论 0 258
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 41,038评论 1 299
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 35,659评论 2 321
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 37,756评论 1 330
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 33,411评论 4 321
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 39,005评论 3 307
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 29,973评论 0 19
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 31,203评论 1 260
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 45,053评论 2 350
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 42,495评论 2 343

推荐阅读更多精彩内容