当前位置: 首页 > 知识库问答 >
问题:

浮点运算中尾数的乘法

高云瀚
2023-03-14

关于尾数(关于浮点运算的指南),实际上如何将两个尾数相乘?

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

假设一个数字的尾数为1.5,将被编码为0b(十进制为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)?

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

一、 e.硬件如何使用存储在内存中的编码尾数来获取新值?


根据指南,浮点数的乘法可以如下实现。我被第二步卡住了。

  1. 从指数中分离出尾数
  2. 将尾数部分相乘(或除)
  3. 将指数加(或减)在一起
  4. 将两个结果合并为新值
  5. 规范化结果值(可选)

共有3个答案

郎飞航
2023-03-14

我发现这段视频回答了我的问题。

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

因此,对于1.5,使用了0b11(3),而不是0B10000000000000000(4194304)
同样,对于1.125,使用0b1001(9)代替0B001000000000000000(1048576)。

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

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


*关于有效位的一些重要信息将在8:05左右解释。对于本例,忽略额外的前导一位就足够了。

罗业
2023-03-14

您需要产品(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

删除隐藏位并舍入尾随位后,该值变为0B10110000000000000。

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

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

洪越泽
2023-03-14

它的工作原理就像小学数学一样简单得多,因为你只需要知道你的乘法表,并记住任何乘以零的东西都是零。

我取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.

指数

0111111 2^0

10000000 2^1

就像小学一样,我们加上指数2^(0 1)=2^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,那么ef都是零,如果d是1,那么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位乘以32的方式工作。进位开始在其他进位的基础上垃圾邮件,数学不是你想手动尝试的东西。这是可能的,但会产生大量的逻辑,单时钟乘法器会消耗芯片的很大一部分,有一些技巧,如。。。使用一个以上的时钟和一根管子,产生一个时钟的错觉。。。

回到以前,我们不能简单地使用太多的逻辑,我们会说一个累加器为零,然后取ab位和两者,d移左零,然后加到累加器中。取ab位和两者,c左移一位,加到累加器中。。。就像我们做纸笔乘法一样。如果您有一个8位*8位,那么乘法至少需要8个时钟。然后是规范化等等。。。

不管怎样,你可以看到,逻辑乘法和我们在小学学到的没有什么不同,只是更简单,因为我们只对0和1进行乘法。要么写零,要么按原样复制操作数。

简而言之,您可能忽略了一点,即存在隐藏/隐含位,没有理由在可用于精度的格式中浪费一点。IEEE 754是1。归一化后尾数为某个幂。

双重相同的故事,暗示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总是存在的(对于正常的、非零的数字)。

还有其他浮点格式,在大多数情况下工作相同,他们可能会更容易为负数等(查找tiDSP格式,例如,如果你能找到它,为速度而不是角落的情况)。

 类似资料:
  • 本文向大家介绍DSP中浮点转定点运算--定点数的加减乘除运算,包括了DSP中浮点转定点运算--定点数的加减乘除运算的使用技巧和注意事项,需要的朋友参考一下 3.定点数的加减乘除运算 简单的说,各种运算的原则就是先把待运算的数据放大一定的倍数,在运算的过程中使用的放大的数据,在最终需要输出结果的时候再调整回去。 举个例来说,有如下运算: 代码的意思是,该模块需要输出一个整型的结果,但计算的过程中有浮

  • 以下是go中的示例代码: 结果线A1、B1和C1之间的差异是可以理解的。然而,从A2开始到C2魔法来了。来自B2和C2的结果都与来自A2线的结果不匹配。对于x2行(x=A、B或C)也是如此——但是x2和x4的输出是相同的。 为了确保,让我们以二进制形式打印结果。 上面代码中的一些事实(一个在bin表单中): 行A11和C11之间有差异(最后一位数字——就在指数之前)。 行A12和C12几乎相同(除

  • 我阅读关于浮点和舍入在浮点算术期间发生的错误。 我读了很多关于IEEE754单精度/双精度格式的文章。我知道有符号位、8(或)11位指数和23(或)52位有效位以及隐式前导位。 我也知道分母不是质因数2的实数不能完全表示,例如二进制中的0.1是0.0001100110011...... 我知道0.1 0.1 0.1不等于0.3,因为舍入误差的累积。 同样,0.5也可以用二进制格式表示,因为它是1/

  • 本文向大家介绍DSP中浮点转定点运算--定点数模拟浮点数运算及常见的策略,包括了DSP中浮点转定点运算--定点数模拟浮点数运算及常见的策略的使用技巧和注意事项,需要的朋友参考一下 4.定点数模拟浮点数运算及常见的策略   相信大家到现在已经大致明白了浮点数转换成定点数运算的概貌。其实,原理讲起来很简单,真正应用到实际的项目中,可能会遇到各种各样的问题。具我的经验,常见的策略有如下几条: 1)除法转

  • 本文向大家介绍DSP中浮点转定点运算--浮点数的存储格式,包括了DSP中浮点转定点运算--浮点数的存储格式的使用技巧和注意事项,需要的朋友参考一下 二:浮点数的存储格式 2.1 IEEE floating point standard   上面我们说了,浮点数的小数点是不固定的,如果每个人都按照自己的爱好存储在电脑里,那不就乱套了吗?那么怎么在计算机中存储这种类型的数字呢?象这类古老的问题前人早都

  • 对于这些代码行,我得到0作为输出,即它们都是相等的。现在,如果我理解正确,a b和c可能会存储稍微不同版本的真值.3因此,当做一个Float.compare(...)对这些值,我希望得到一个输出值,而不是0。为什么我把它们取为0?