尾数乘法中的尾数乘法

时间:2018-02-18 23:02:58

标签: floating-point hardware fpu

关于尾数(re this guide on floating point arithmetic),你如何实际将两个尾数相乘?

假设IEEE 754单精度浮点表示。

假设一个数字的尾数为1.5,其编码为0b10000000000000000000000(十进制为4194304)。第二个数字的尾数为1.125,其编码为0b00100000000000000000000(十进制为1048576)。

1.5 x 1.125 = 1.6875

1.6875编码为0b10110000000000000000000(十进制为5767168)。但4194304 * 1048576不等于5767168 ...

尾数乘法如何使4194304(1.5)乘以1048576(1.125),得到5767168(1.6875)?

也就是说,你如何将编码的尾数相乘?

即。硬件如何使用存储在内存中的编码尾数来获取新值?


the guide开始,浮点数的乘法可以如下实现。我被困在第2步。

  
      
  1. 将尾数与指数分开
  2.   
  3. 将尾数部分乘以(或除以)
  4.   
  5. 一起添加(或减去)指数
  6.   
  7. 将两个结果合并为新值
  8.   
  9. 规范化结果值(可选)
  10.   

3 个答案:

答案 0 :(得分:0)

您想要产品(1.0 * 2 -1 )*(1.0 * 2 -3 )。

尾数是1和1,指数是-1和-3。

因此尾数的乘积为1 * 1 = 1,指数之和为(-1)+( - 3)= -4。

因此,根据步骤1至4,两个因子的乘积为1 * 2 -4 = 0.0625。

要记住两个重要的事项:(1)二进制IEEE 754浮点中的指数总是表示2的幂,以及(2)归一化尾数的整数部分总是1(因此第一位可以隐藏在数字的实际二进制表示中。

编辑:自问题被重写后,将我的一些评论纳入此答案。

您链接的指南似乎描述了行为,但没有描述实施。如果实现如此简单,我认为浮点数学将与整数数学一样快。

对于尾数,硬件可能会做某些事情,例如在某个时刻添加回隐藏位,这样就可以了

0b110000000000000000000000 * 0b100100000000000000000000 = 0b11011000000000000000000000000000000000000000000

在删除隐藏位并舍去尾随位后,这将变为0b10110000000000000000000。

对于指数,硬件可以从两个因子的偏差指数中减去127,执行算术,然后将127加回到求和或差值以重新偏置指数。

请记住,64位格式用于对内存中的数字进行紧凑编码,但这可能不是执行数学时使用的实际表示形式。处理器甚至可以以80位精度执行中间数学运算,然后在将值写回存储器时将结果舍入为64位。请参阅x87 80-bit double-extended precision

答案 1 :(得分:0)

它的工作原理与小学数学相似,因为你只需知道你的乘法表,并记住任何时候零都是零。

让我拿1.5 * 3.0,单精度。

0x3FC00000  1.5
0x40400000  3.0
0x40900000  1.5 * 3.0 = 4.5

扩展

0x3FC0
0011111111000000
0 01111111 1000000

0x4040
0100000001000000
0 10000000 1000000

所以在二进制中我们乘以1.1乘以1.1,就像小学一样,除了更容易

  11
* 11
======
  11 
+11
======
1001

然后我们从一个操作数和另一个操作数中有一个(非)十进制(二进制?)位置,所以我们的句点从右边开始有两个。

10.01

但我们需要规范化

1.001 with an increase in the exponent.

指数

01111111 2 ^ 0

10000000 2 ^ 1

就像小学一样,我们添加指数2 ^(0 + 1)= 2 ^ 1。然后我们将另一个移位加1到指数2 ^(1 + 1)= 2 ^ 2进行归一化。

0 10000001 001000....
010000001001000....
0100 0000 1001 000....

给出与计算机生成的结果相匹配的结果

0x40900000

没有魔力。

硬件中的乘法与小学没有什么不同,它只是更简单。查看这些单独的位a是0或1位,b是位0还是1,依此类推。

   ab
*  cd
======
   ef
  gh
======
 jklm

如果d为0,则如果d为1,则ef均为零,则ef = ab 所以到目前为止的方程是

e = a & d
f = b & d
g = a & c
h = b & c

任何以0结尾的东西都是0,任何以1结尾的东西本身就是。

然后我们做补充

 nop0
   ef
+ gh
======
 jklm

我在这里做了一些重作弊两位加,执行和结果,真值表

xy cr
00 00 
01 01
10 01
11 10

结果为x或y,执行为x和y

m = f
p = 0 because f+0 cant have a carry bit.
l = e xor h 
o = e & h 
k = o xor g
n = o & g
j = n

替换,希望我不会犯任何(更多)错误

m = f = b & d
l = e xor h = (a&d) xor (b&c)
k = o xor g = (e & h) xor (a&c) = ((a&d) & (b&c)) xor (a&c)
j = n = o & g = (e & h) & (a&c) = ((a&d) & (b&c)) & (a&c)

因此可能存在一些优化,但如果您需要/想要在一个时钟周期内计算两位乘二位乘法器,那么就有输入和输出方程式。很多作弊,因为做3x3而且加法变得更糟。按照8位或8位或32位的方式进行工作.B。在其他进位位上开始进行垃圾邮件,数学运算不是您想要手动尝试的。这是可能的,但是会产生大量的逻辑,单个时钟乘法器会占用你芯片的很大一部分,有一些技巧......使用一个以上的时钟和一个管道给人一种时钟的错觉......

回到过去的日子里,我们根本无法燃烧那么多的逻辑,我们会说零累加器,然后取ab位和两者,d左移零,然后加到累加器。取b位并且两个都向左移动c并添加到累加器......就像我们做纸和铅笔乘法一样。如果你有一个8位* 8位,则只需要乘法至少8个时钟。然后归一化等等......

无论如何,你可以看到逻辑上的乘法与我们在小学时学到的相比没有什么不同,因为我们只是乘以0和1.你可以写零或按原样复制操作数。

简短的回答,你可能错过了隐藏/暗示位的观点,没有理由浪费一点可用于精确的格式。当标准化时,IEEE 754对于某些功率是1.mantissa。

双重相同的故事,暗示1.mantissa:

0x3FF8000000000000 1.5
0x4008000000000000 3.0
0x4012000000000000 4.5

0011111111111000
0100000000001000
0100000000010010

0 01111111111 1000   1.1000...
0 10000000000 1000   1.1000...
0 10000000001 0010   1.0010....

另一种看待这个没有小数点的方法(或暗示它们并且它们不是小数点,而是我猜的二进制点)。

从1.10000以上...... * 1.10000是0xC00000 * 0xC00000 = 0x900000000000,48位。我们将一半的位剥离到0x900000,因为我们有一个1位和47位的尾数,但只有23位的空间,所以我们切断了24位低位,无论是零还是任何其他数字。我们保留了一半的比特并丢弃了一半的比特,这并不是偶然的。现在它已经是1.000 ... * 1.000 ......我们将有0x400000000000 1和46位斩波23而不是24位。您可以使用较少的位数进行一些实验,但请记住,与任何两个相互重叠的N位数字不同,我们在顶部有一个隐含/固定1。所以(1 * 2 ^ 23)*(1 * 2 ^ 23)=(1 * 1)*(2 ^(23 + 23)= 1 * 2 ^ 46总是在尾数乘以时(正常,非 - 零,数字)。

还有其他浮点格式在大多数情况下都是相同的,它们可能更容易用于负数等等(例如,如果你能找到它,请查看ti DSP格式,为速度而不是极端情况而构建)。

答案 2 :(得分:-1)

我发现this video回答了我的问题。

要将编码值相乘,硬件会以某种方式忽略拖尾零。还放置了一个前导位。

因此,对于1.5,使用0b11(3)代替0b10000000000000000000000(4194304)。
同样,对于1.125,使用0b1001(9)代替0b00100000000000000000000(1048576)。

因此0b11 * 0b1001 = 0b11011(27)。

如果忽略0b11011中的额外前导位*并添加尾随零,则以0b10110000000000000000000结尾(5767168)。


* around 8:05解释了重要位的重要内容。对于这个例子,可以忽略额外的前导一位就足够了。