数据表示基础:浮点数
在中世纪,有些人认为左撇子是邪恶的,这是一个负面的观点。因此,如果你忘记了小数点应该向哪个方向移动,负指数向左移动。而正指数则向右移动。 |
如果你学习了物理或化学等其他学科,你可能会遇到这样的浮点数
(Planck's constant)
第一位定义了数字的非零部分,称为尾数,第二部分定义了我们要移动小数点的位数,这被称为指数,当小数点向右移动时可以是正数,当小数点向左移动时可以是负数。
如果你想完整写出这个数字,你需要在指数中将小数点向左移动 34 位,得到
这将花费很多时间来写,而且人眼很难看清有多少个零。因此,当我们可以接受一定程度的精度(6.63 = 3 位有效数字)时,我们可以用少数位数存储像普朗克常数这样的多位数。你总是权衡数字的范围(或范围)与其精度(有效位的数量)。
二进制数也是如此,而且更为重要。在处理数字及其计算表示时,你必须始终注意这些数字在内存中会占用多少空间。正如我们在上面的例子中看到的,一个数字的非浮点表示可能占用不可接受的位数,想象一下,你需要用多少位来存储 在二进制中‽
一个二进制浮点数可能包含 2、3 或 4 个字节,但是你只需要关注 2 字节(16 位)的类型。前 10 位是尾数,后 6 位是指数。
就像十进制('基数 10','十进制')浮点数表示一样,二进制浮点数将有一个尾数和一个指数,但由于你正在处理二进制(基数 2),你必须记住,你不是使用 ,而是必须使用 .
定点二进制允许计算机保存小数,但由于其性质,其范围非常有限。即使使用 4 个字节来保存每个数字,并将小数点后的分数部分用 8 位表示,可以保存的最大数字也只有 800 多万。需要另一种格式来保存非常大的数字。
在十进制中,可以用尾数和指数来表示非常大的数字。例如 0.12*10²。这里的 0.12 是尾数,而 10² 是指数。尾数保存主要数字,而指数定义了小数点应该放置的位置。
相同的技术可以用于二进制数。例如,可以将两个字节分成 10 位用于尾数,剩余的 6 位用于指数。这允许使用更大范围的数字。
在计算二进制浮点数时,需要经过几个步骤。事实上,这很像迪斯科舞曲的舞蹈套路 - 在这个页面上被称为 Noorgat 舞蹈,Kemp 变奏(你不会被考查名称,但它应该能帮助你记住)
- 符号 - 找到尾数的符号(记下来)
- 滑动 - 找到指数的值,以及它是正还是负
- 反弹 - 根据指数的要求移动小数点,负指数向左移动,正指数向右移动
- 如果向左移动并且是正数,则用零填充
- 如果向左移动并且是负数,则用一填充
- 翻转 - 如果尾数为负数,则对其进行二进制补码运算
- 游动 - 从小数点开始,从左到右计算尾数的值。现在确保你参考你在符号移动中记录的符号。
示例:二进制浮点数示例 让我们试一试。我们给定以下 16 位浮点数,其中 10 位用于尾数,6 位用于指数。请记住,小数点位于第一位和第二位有效位之间 我们需要执行的第一个操作是 符号,找出尾数的符号
It is 0 so the mantissa is positive
Noorgat 舞蹈的第二步是 滑动,我们需要找到指数的值,即数字的最后 6 位
So we know that the exponent is of size positive one and we will have to move the decimal point
one place to the right.
Noorgat 舞蹈的第三步是 反弹,即将尾数的小数点移动由滑动指定的位数,在本例中是向右移动一位。就像这样 第四步是可选的 翻转。查看符号阶段并查看尾数是否为负数。不是吗?好吧,你可以跳过这一步,因为我们只在尾数为负数时翻转数字。 第五步也是最后一步是 游动。单独考虑尾数,我们可以现在计算出浮点数的值。从中心开始,将左侧的每个数字标记为 等等。右侧的每个数字 等等。
Voila! the answer is 1
|
练习:简单二进制浮点数 使用 10 位尾数和 6 位指数计算以下数字的十进制值 0.001101000 000110 答案 1. 符号:尾数以零开头,因此它是一个 正数。 000110 = +6 3. 反弹:我们需要移动尾数中的小数点。在本例中,指数为 正,因此我们需要将小数点向右移动 6 位 0.001101000 -> 0001101.000 4. 翻转:由于数字不是负数,因此我们不需要这样做 1+4+8 = +13 FINISHED! 0 101000000 111111 答案 1. 符号:尾数以零开头,因此它是一个 正数。 111111 It starts with a one therefore it is a negative number 000001 = -1 3. 反弹:我们需要移动尾数中的小数点。在本例中,指数为 负,因此我们需要将小数点向左移动 1 位 0.101000000 -> 0.0101000000 4. 翻转:由于尾数不是负数,因此我们不需要这样做 1/4 + 1/16 = +0.3125 FINISHED! 1 011111010 000101 答案 1. 符号:尾数以 1 开头,因此它是一个 负数。 000101 = +5 3. 反弹:我们需要移动尾数中的小数点。在本例中,指数为 正,因此我们需要将小数点向右移动 5 位 1.011111010 -> 101111.1010 4. 翻转:尾数为负数,如步骤 1 中所述,因此我们需要转换此数字 101111.1010 -> 010000.0110 5. 游动:计算小数点左侧和右侧的值 16+1/4+1/8 = -16.375 FINISHED! 1 101000000 111101 答案 1. 符号:尾数以 1 开头,因此它是一个 负数。 111101 It starts with a one therefore it is a negative number 000011 = -3 3. 反弹:我们需要移动尾数中的小数点。在本例中,指数为 负,因此我们需要将小数点向左移动 3 位。仔细观察! 1.101000000 -> 1.111101000000 note that we placed extra ones on the front of the number. Consider the exponent being negative and the mantissa positive, we would add extra zeros on the front 0.01 * 2^-3 = 0.00001 If both are negative placing zeros in front of the mantissa would make it positive! Therefore, we need to add extra ones to keep the mantissa negative With the flip we'll lose these 'extra' ones 4. 翻转:尾数为负数,如步骤 1 中所述,因此我们需要转换此数字 1.111101000000 -> 0.000011000000 5. 游动:计算小数点左侧和右侧的值 1/32+1/64 = -0.046875 Remember the number was negative! FINISHED! 1 111111010 000011 答案 1. 符号:尾数以 1 开头,因此它是一个 负数。 000011 = +3 3. 反弹:我们需要移动尾数中的小数点。在本例中,指数为 正,因此我们需要将小数点向右移动 3 位。 1.111111010 -> 1111.111010 4. 翻转:尾数为负数,如步骤 1 中所述,因此我们需要转换此数字 1111.111010-> 0000.000110 5. 游动:计算小数点左侧和右侧的值 1/16+1/32 = -0.09375 Remember the number was negative! FINISHED! |
你可能还会被要求将一个十进制数转换为其二进制浮点数等效值。
- 计算二进制等效值
- 计算移动二进制小数点的距离 (y)
- 将指数设置为移动二进制小数点的位数的反向 (-y)
- 用额外的位填充数字
示例:十进制数转换为二进制浮点数 如果我们被要求将十进制数 39.75 转换为二进制浮点数,我们首先需要找出二进制等效值 128 64 32 16 8 4 2 1 . ½ ¼ ⅛ 0 0 1 0 0 1 1 1 . 1 1 0 我们需要将二进制小数点向左移动多少位才能使数字标准化? 0 0 . 1 0 0 1 1 1 1 1 0 (6 places to the left) 因此,为了使小数点回到它开始的位置,我们需要将它向右移动 6 位。6 现在成为你的指数。 0.100111110 | 000110 如果你想检查你的答案,将上面的数字转换为十进制数。你会得到 39.75! |
练习:简单二进制浮点数 使用 10 位尾数和 6 位指数计算以下数字的二进制浮点数 67 答案 128 64 32 16 8 4 2 1 . ½ ¼ ⅛ 0 1 0 0 0 0 1 1 . 0 0 0 我们需要将二进制小数点向左移动多少位才能使数字标准化? 0 . 1 0 0 0 0 1 1 0 0 0 (7 places to the left) 为了使前部标准化,我们必须将小数点移动 7 位。(将它移动 6 位会使数字变为负数!) 0.100001100 | 000111 23.25 答案 128 64 32 16 8 4 2 1 . ½ ¼ ⅛ 0 0 0 1 0 1 1 1 . 0 1 0 我们需要将二进制小数点向左移动多少位才能使数字标准化? 0 0 0 . 1 0 1 1 1 0 1 0 (5 places to the left) 为了使前部标准化,我们必须将小数点移动 5 位。(将它移动 4 位会使数字变为负数!) 0.101110100 | 000101 123.875 答案 128 64 32 16 8 4 2 1 . ½ ¼ ⅛ 0 1 1 1 1 0 1 1 . 1 1 1 我们需要将二进制小数点向左移动多少位才能使数字标准化? 0 . 1 1 1 1 0 1 1 1 1 1 (7 places to the left) 为了使前部标准化,我们必须将小数点移动 7 位。 0.1111011111 | 000111 但这使用的是 11 位尾数,我们必须舍弃一位,从而损失精度! 0.111101111 | 000111 128.25 答案 128 64 32 16 8 4 2 1 . ½ ¼ ⅛ 1 0 0 0 0 0 0 0 . 0 1 0 我们需要将二进制小数点向左移动多少位才能使数字标准化? 0.1 0 0 0 0 0 0 0 0 1 0 (8 places to the left) 为了使前部标准化,我们必须将小数点移动 8 位。(将它移动 7 位会使它变为负数!) 0.100000000 | 001000 请注意,我们必须舍弃 .25,因为它不适合 10 位尾数。 -513 答案 1024 512 256 128 64 32 16 8 4 2 1 . ½ ¼ ⅛ 0 1 0 0 0 0 0 0 0 0 1 . 0 0 0 使用翻转规则将其转换为负数形式 1024 512 256 128 64 32 16 8 4 2 1 . ½ ¼ ⅛ 1 0 1 1 1 1 1 1 1 1 1 . 0 0 0 我们需要将二进制小数点向左移动多少位才能使数字标准化? 1 . 0 1 1 1 1 1 1 1 1 1 0 0 0 (10 places to the left) 为了使前部标准化,我们必须将小数点移动 10 位。 1.011111111 | 001010 请注意,我们必须舍弃最后一个 1,因为它不适合 10 位尾数。这意味着显示的数字只是 10111111110.0 将其转换为十进制数 01000000010.0 = -514 你很快就会了解使用浮点数的误差 |
当你有一个 16 位数字,其中尾数为 10 位,指数为 6 位时
最大正数将是
Mantissa: 0.111111111 Exponent: 011111
最小正数将是
Mantissa: 0.000000001 Exponent: 100000
最大负数将是
Mantissa: 1.000000000 Exponent: 011111
最小负数将是
Mantissa: 1.111111111 Exponent: 100000