补码的乘法-布斯乘法

前言

本篇文章讲解如何通过逻辑门的形式来实现补码的乘法操作

布斯乘法

A.D.Booth提出了一种补码相乘算法,可以将符号位与数值位合在一起参与运算,直接得出用补码表示的乘积,且正数和负数同等对待。这种算法被称之为Booth (布斯)乘法
下面有两个变量值 X X X Y Y Y
Y Y Y用二进制表示为
Y = y n − 1 y n − 2 … y 2 y 1 y 0 Y = y_{n-1}y_{n-2}\ldots y_2y_1y_0 Y=yn1yn2y2y1y0
因为Y是用补码表示的,所以Y的值可以通过下面的公式计算:
Y = − y n − 1 2 n − 1 + y n − 2 2 n − 2 + … + y 1 2 1 + y 0 2 0 = − y n − 1 2 n − 1 + ∑ i = 0 n − 2 y i 2 i = − y n − 1 2 n − 1 + y n − 2 2 n − 1 − y n − 2 2 n − 2 + … + y 1 2 2 − y 1 2 1 + y 0 2 1 − y 0 = ( y n − 2 − y n − 1 ) 2 n − 1 + ( y n − 3 − y n − 2 ) 2 n − 2 + … + ( y 0 − y 1 ) 2 1 + ( 0 − y 0 ) = ∑ i = 0 n − 1 ( y i − 1 − y i ) 2 i \begin{aligned} Y &= -y_{n-1}2^{n-1} + y_{n-2}2^{n-2} + \ldots+y_12^1+ y_02^0\\ &=-y_{n-1}2^{n-1} + \sum_{i=0}^{n-2}y_i2^i \\ &=-y_{n-1}2^{n-1} + y_{n-2}2^{n-1}-y_{n-2}2^{n-2}+\ldots+y_12^{2}-y_{1}2^{1}+y_02^{1}-y_0\\ &=(y_{n-2}-y_{n-1})2^{n-1}+(y_{n-3}-y_{n-2})2^{n-2}+\ldots+(y_0-y_1)2^1+(0-y_0)\\ &=\sum_{i=0}^{n-1}(y_{i-1}-y_{i})2^{i} \end{aligned} Y=yn12n1+yn22n2++y121+y020=yn12n1+i=0n2yi2i=yn12n1+yn22n1yn22n2++y122y121+y021y0=(yn2yn1)2n1+(yn3yn2)2n2++(y0y1)21+(0y0)=i=0n1(yi1yi)2i
因为 X X X Y Y Y都是n位数据,所以 X × Y X\times Y X×Y可能占用2n位。
我们先假设 Y Y Y乘以 2 − n 2^{-n} 2n
X × Y × 2 − n = X × ∑ i = 0 n − 1 ( y i − 1 − y i ) 2 i × 2 − n = X × ∑ i = 0 n − 1 ( y i − 1 − y i ) 2 − ( n − i ) = P n \begin{aligned} X\times Y\times2^{-n} &= X\times \sum_{i=0}^{n-1}(y_{i-1}-y_{i})2^{i}\times2^{-n}\\ &=X\times \sum_{i=0}^{n-1}(y_{i-1}-y_{i})2^{-(n-i)}\\ &=P_{n} \end{aligned} X×Y×2n=X×i=0n1(yi1yi)2i×2n=X×i=0n1(yi1yi)2(ni)=Pn
即然我们假设这个值等于 P n P_{n} Pn了,那么我们可以推测 P n − 1 P_{n-1} Pn1的值
P n − 1 = X × ∑ i = 0 n − 2 ( y i − 1 − y i ) 2 − ( n − 1 − i ) P_{n-1} = X\times \sum_{i=0}^{n-2}(y_{i-1}-y_{i})2^{-(n-1-i)} Pn1=X×i=0n2(yi1yi)2(n1i)
然后我们能得出两个挨着的一般性公式 P i P_{i} Pi P i − 1 P_{i-1} Pi1的关系
P i = 2 − 1 ( P i − 1 + ( y i − 2 − y i − 1 ) X ) , i = 1 , 2 … , n − 1 P_{i} = 2^{-1}(P_{i-1} + (y_{i-2}-y_{i-1})X),i = 1,2\ldots,n-1 Pi=21(Pi1+(yi2yi1)X)i=1,2,n1

根据上面的公式,我们发现,可以先计算 P 0 P_{0} P0,然后通过 P 0 P_{0} P0计算 P 1 P_{1} P1,然后通过 P 1 P_{1} P1计算 P 2 P_{2} P2,然后就可以依次往后计算出 P n P_{n} Pn,如果计算 X × Y X\times Y X×Y,我们可以按照下面的步骤进行:

  1. 假设 P 0 = 0 P_{0}=0 P0=0,假设 y − 1 = 0 y_{-1}=0 y1=0
  2. 从y的最右侧位开始,先比较 y 0 y_0 y0 y − 1 y_{-1} y1
  3. 如果 y 0 y − 1 = = 00 y_0y_{-1}==00 y0y1==00 P 0 P_0 P0右移一位
  4. 如果 y 0 y − 1 = = 01 y_0y_{-1}==01 y0y1==01 P 0 + X P_0+X P0+X然后,右移一位
  5. 如果 y 0 y − 1 = = 10 y_0y_{-1}==10 y0y1==10 P 0 − X P_0-X P0X然后,右移一位
  6. 如果 y 0 y − 1 = = 11 y_0y_{-1}==11 y0y1==11 P 0 P_0 P0右移一位
  7. 右移后得到 P 1 P_{1} P1,比较位向左移动一位,如果没有超过最大位,跳转到2
  8. 如果超过最高位了, P n P_n Pn就是结果

注意:在此之前,其实 P n = X × Y × 2 − n P_n =X\times Y\times2^{-n} Pn=X×Y×2n,并且我们发现在上述步骤中结果一直在向右移,所以,我们可以把初始结果放在高n位上,这样向右移动不会丢失数据,并且也相当于乘了 2 n 2^{n} 2n,结果刚好是想要的值。

通过上面的步骤可以看出,乘法被分解成一系列加减和移位操作的顺序集合,我们之前已经实现了串行进位加法器和并行进位加法器,并且实现了一个桶形移位器

下面看一个实际的例子:
假设X = 100,Y = 120;
用二进制表示为X = 01100100,Y= 01111000,即然8位能够放下数据,为了书写方便,我们假设XY都为8位,结果为16位数据,假设结果为R = 0;

  1. 比较 y 0 y_0 y0 y − 1 y_{-1} y1, y 0 y − 1 = 00 y_0y_{-1}=00 y0y1=00,R=00000000 00000000,右移后值不变
  2. 比较 y 1 y_1 y1 y 0 y_0 y0, y 1 y 0 = 00 y_1y_0=00 y1y0=00,R=00000000 00000000,右移后值不变
  3. 比较 y 2 y_2 y2 y 1 y_1 y1, y 2 y 1 = 00 y_2y_1=00 y2y1=00,R=00000000 00000000,右移后值不变
  4. 比较 y 3 y_3 y3 y 2 y_2 y2, y 3 y 2 = 10 y_3y_2=10 y3y2=10,R=00000000 00000000,R-X后右移
    R-X = R(高位) + (~X) + 1= 10011100 00000000,右移后为11001110 00000000
    注意:是在R的高位上操作,并且右移为算数右移,补符号位
  5. 比较 y 4 y_4 y4 y 3 y_3 y3, y 4 y 3 = 11 y_4y_3=11 y4y3=11,R=11001110 00000000,右移后为11100111 00000000
  6. 比较 y 5 y_5 y5 y 4 y_4 y4, y 5 y 4 = 11 y_5y_4=11 y5y4=11,R=11100111 00000000,右移后为11110011 10000000
  7. 比较 y 6 y_6 y6 y 5 y_5 y5, y 6 y 5 = 11 y_6y_5=11 y6y5=11,R=11110011 10000000,右移后为11111001 11000000
  8. 比较 y 7 y_7 y7 y 6 y_6 y6, y 7 y 6 = 01 y_7y_6=01 y7y6=01,R=11111001 11000000,R+X后右移,R+X = 01011101 11000000, 右移后为00101110 11100000

计算完成,00101110 11100000 = 12000,与结果相符

布斯乘法在电路的实现

我们在前面讲述算法执行过程的时候,把结果数据放在了高n位,这样有两个好处:

  • 正好抵消了之前公式中乘的 2 − n 2^{-n} 2n
  • 在算法执行过程中结果数据总要右移,把结果数据放在高位,右移的时候不会丢失数据

并且每一步我们都会从右往左比较Y的位值,相当于我们每步都右移Y,然后比较Y的最低两位,但是第一步的时候我们还有一个 y − 1 = 0 y_{-1}=0 y1=0,所以我们可以这么设计:

  • 假设Y有n位,我们设计的电路有n+1根线,Y的值放在 n ~ 1 n~1 n1位, y − 1 y_{-1} y1的值放在0位
  • 这样,每一步的比较操作我们只需要右移电路一位,然后比较最低的两位值即可

即然结果数据和Y的值都右移,并且每步骤都右移1位,那么我们可以设计一个通用的电路:

  • 假设Y有n位,我们设计的电路有2n+1位,数据结果保存到 2 n ~ n + 1 2n~n+1 2nn+1位,Y的值放在 n ~ 1 n~1 n1位, y − 1 y_{-1} y1的值放在0位
  • 最终的结果就是高2n位的数据

下面给出电路图:
在这里插入图片描述

图中表示的是32位的布斯乘法电路图,电路的执行步骤如下:

  • 我们假设乘积寄存器P+乘数寄存器Y+最右边保存 y − 1 y_{-1} y1的值统称为R。
  • 默认乘积寄存器P的值为0,最右边保存 y − 1 y_{-1} y1的值为0,乘数寄存器Y的值和被乘数寄存器X的值被输入,计数器为0,时钟用来增加计数器的值
  • 每一步时钟,检查R的第两位,根据值的不同执行不同的电路逻辑
    • 00或者11,R右移,执行下一步
    • 01,执行加法操作,结果保存到乘积寄存器P,R右移,执行下一步
    • 10,执行减法操作,结果保存到乘积寄存器P,R右移,执行下一步
  • 计数器等于32,输出结果乘积寄存器P+乘数寄存器Y,结束

算术一位右移

虽然我们实现了桶形移位器,但是在当前的乘法运算中,有点大材小用,如果我们仅仅实现一个一位的右移操作,电路将变得很简单,我们直接给出C语言描述git地址

/*** 单位右移操作,为了实现布斯乘法专门定义的右移电路,支持129位* in_1:128~65位,用于存放乘积寄存器P* in_2:64~1位,用于存放乘数寄存器Y* in_1:0位,用于存放临时比较的值* isLogic:是否是逻辑右移*/
extern void alu_shift_right_1(long* in_1,long*  in_2,long*  in_3,long isLogic);void alu_shift_right_1(long* in_1,long* in_2,long*  in_3,long isLogic)
{// 先赋值最低位*in_3 = (*in_2)&1;// in_1的最低位给in_2的最高位unsigned long a = *in_2;*in_2 = (a>>1)| ((*in_1)&1)<<(sizeof(long)*8-1);// in_1右移1位if(isLogic){unsigned long b = *in_1;*in_1 = b>>1;}else{*in_1 = (*in_1)>>1;}
}

布斯乘法的C语言描述

最后给出布斯乘法的C语言描述,我们把结果存在两个long类型的数值中,out_1保存高位,out_2保存低位。git地址

/*** 使用布斯乘法算法计算两个数相乘* in_1:输入1* in_2:输入2* out_1:输出高位* out_2:输出低位*/
extern void alu_booth_times(long in_1, long in_2,long* out_1, long* out_2);void alu_booth_times(long in_1, long in_2,long* out_1, long* out_2)
{// y-1位,默认为0long lastBit = 0;// 保存结果的高位*out_1 = 0;long c = 0;// 计数器for(int i = 0; i<sizeof(long)*8;i++){long temp = in_2&1;if(temp == lastBit)// 直接右移{alu_shift_right_1(out_1,&in_2,&lastBit,0);}else if(lastBit==1)// 01,相加,然后右移{c = 0;*out_1 = alu_add_bcla_64(*out_1,in_1,sizeof(long)*8,&c);alu_shift_right_1(out_1,&in_2,&lastBit,0);}else// 10,相减,然后右移{*out_1 = alu_sub_bcla_64(*out_1,in_1,sizeof(long)*8);alu_shift_right_1(out_1,&in_2,&lastBit,0);}}*out_2 = in_2;
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.mzph.cn/news/598141.shtml

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈email:809451989@qq.com,一经查实,立即删除!

相关文章

【量化金融】《证券投资学》吴晓求(第四版)(更新中)

这里写目录标题 第一篇 基本知识第1章 证券投资工具名词解释简答题 第2章 证券市场名词解释简答题 第二篇 基本分析第三篇 技术分析第四篇 组合管理第五篇 量化分析与交易策略 第一篇 基本知识 第1章 证券投资工具 名词解释 风险&#xff08;risk&#xff09; 未来结果的不…

【hcie-cloud】【16】业务上云迁移、Rainbow详述

文章目录 前言华为业务迁移解决方案概述业务上云背景概述业务迁移场景需求及挑战业务迁移的价值华为业务迁移解决方案 - 全景图华为业务迁移解决方案的优势 Rainbow迁移工具介绍Rainbow迁移原理介绍Rainbow迁移工具简介Rainbow迁移工具定位Rainbow迁移视图Rainbow迁移原理 - Wi…

JumpServer3.0版本-账号管理

账号列表 我这里已经创建好了所以有很多,可以点击资产树列表分类查看 点击创建按钮,添加账号 资产:如果多个设备的账号密码一致可以在资产同事选中 名称:方便辨识即可 用户名:登录设备的账户名 密码:按你登录需求自行选择 添加按钮旁边还有个“模版添加” 此功能便…

yolov8实战第五天——yolov8+ffmpg实时视频流检测并进行实时推流——(推流,保姆教学)

yolov8实战第一天——yolov8部署并训练自己的数据集&#xff08;保姆式教程&#xff09;_yolov8训练自己的数据集-CSDN博客 yolov8实战第三天——yolov8TensorRT部署&#xff08;python推理&#xff09;&#xff08;保姆教学&#xff09;-CSDN博客 今天&#xff0c;我们继续y…

Java TBA访问NetSuite Restlet时的403错误

本周有同学问为啥Java访问NetSuite Restlet时&#xff0c;按照知识会之前的文章分享&#xff0c;会一直报403 INVALID_LOGIN_ATTEMPT错误。 https://nk-community.blog.csdn.net/article/details/131399801https://nk-community.blog.csdn.net/article/details/131399801原因是…

线程同步之:QReadWriteLock

1、 使用互斥量QMutex时候存在一个问题 每次只能有一个线程获得互斥量的权限。如果在一个程序中有多个线程“读”取某个变量&#xff0c;使用互斥量时也必须排队&#xff01; 然而&#xff0c;实际情况是允许&#xff1a;让多个线程同时“读”&#xff01; 这样互斥量 就会降…

面试官:说说flexbox(弹性盒flex布局),以及适用场景?

面试官&#xff1a;说说flexbox&#xff08;弹性盒布局模型&#xff09;,以及适用场景&#xff1f; 一、是什么 Flexible Box 简称 flex&#xff0c;意为”弹性布局”&#xff0c;可以简便、完整、响应式地实现各种页面布局 采用Flex布局的元素&#xff0c;称为flex容器conta…

面试官:线程池的7种创建方式,你都清楚吗?

文章目录 前言1. 固定数量的线程池a. 线程池返回结果b. ⾃定义线程池名称或优先级 2. 带缓存的线程池3. 执⾏定时任务a. 延迟执行(一次)b. 固定频率执行c. scheduleAtFixedRate VS scheduleWithFixedDelay 4. 定时任务单线程5. 单线程线程池6. 根据当前CPU⽣成线程池 前言 线程…

CRM管理系统八大特性,如何帮助企业提升业务效能?

CRM管理系统的使用率逐年上升&#xff0c;这离不开企业对客户的依赖——管理好客户关系是企业发展你的重要因素&#xff0c;由此可见CRM对于任何成长中的企业都是必不可少的。以前我们写过很多关于CRM功能的文章&#xff0c;这篇文章换个思路&#xff0c;想一想CRM管理系统主要…

Pytorch从零开始实战15

Pytorch从零开始实战——ResNeXt-50算法实战 本系列来源于365天深度学习训练营 原作者K同学 文章目录 Pytorch从零开始实战——ResNeXt-50算法实战环境准备数据集模型选择开始训练可视化总结 环境准备 本文基于Jupyter notebook&#xff0c;使用Python3.8&#xff0c;Pytor…

Unity中Shader序列图动画(UV流动的通用起始点)

文章目录 前言一、一般序列帧动画是按照序列图如下顺序读取的二、在Shader找到UV流动的起始点1、先实现纹理采样2、得到 uv 走格的单位格子大小3、定位到左上角为起始单位格 三、使UV流动的起始点通用化1、在属性面板接收 行 和 列的属性2、看图片可以总结出第一个单元格的公式…

Kotlin/JS工程构建及编译运行到浏览器

概述 Kotlin/JS 提供了转换 Kotlin 代码、Kotlin 标准库的能力&#xff0c;并且兼容 JavaScript 的任何依赖项。Kotlin/JS 的当前实现以 ES5 为目标。 使用 Kotlin/JS 的推荐方法是通过 kotlin.multiplatform Gradle 插件。它提供了一种集中且便捷的方式来设置与控制以 JavaS…

华为DriveONE电机控制器拆解实拍

如果说之前的问界M5、M7&#xff0c;华为让我们看到其在智能化上确实拥有遥遥领先的能力&#xff0c;那么在智界S7上&#xff0c;则让我们看到华为在动力、底盘这些硬件执行层面&#xff0c;竟然也有不输给很多车企的实力。1、华为电驱&#xff0c;全球第一&#xff1f;在智界S…

8K超高清应用:输电线网智慧巡检提升巡视效率

电力安全关系国计民生&#xff0c;是国家安全的重要保障&#xff0c;因此确保电力线路系统的安全运行至关重要。电力线路系统整体分为三大板块&#xff1a;输电线路、变电站和配电线路。然而&#xff0c;由于自然灾害、人为破坏等因素影响&#xff0c;这三大板块的设备很容易发…

开启Hyper-V

开启Hyper-V 为了给windows-ltsc激活&#xff0c;只好给系统装个虚拟机服务器。VMware太大了&#xff0c;于是想起Hyper-V。 走起。 在搜索栏直接搜索“windows功能”就能找到“开启或关闭windows功能”&#xff0c;直接勾选Hyper-V&#xff0c;就能安装了。重启后&#xff0c;…

不同阶数的巴特沃斯低通滤波器的空间域表示——数字图像处理

原理 巴特沃斯低通滤波器&#xff08;Butterworth Low-Pass Filter&#xff09;在频率域中的定义是明确的&#xff0c;但它在空间域中的表示不是直观的。这是因为巴特沃斯滤波器的形式是基于频率的&#xff0c;并且其空间域表示涉及到一个复杂的逆傅里叶变换&#xff0c;该变换…

透明展示柜的安装方法

透明展示柜的安装方法主要包括以下步骤&#xff1a; 准备工具和材料&#xff1a;在安装前&#xff0c;需要准备相应的工具和材料&#xff0c;如螺丝刀、电钻、固定架、玻璃板、胶水等。 确定安装位置&#xff1a;选择一个合适的安装位置&#xff0c;确保展示柜的摆放位置合理&…

关于“Python”的核心知识点整理大全62

目录 20.2.2 安装 Heroku Toolbelt 20.2.3 安装必要的包 注意 20.2.4 创建包含包列表的文件 requirements.txt requirements.txt requirements.txt 注意 20.2.5 指定 Python 版本 runtime.txt 注意 20.2.6 为部署到 Herohu 而修改 settings.py settings.py 20.2.7…

SparkStreaming基础解析(四)

1、 Spark Streaming概述 1.1 Spark Streaming是什么 Spark Streaming用于流式数据的处理。Spark Streaming支持的数据输入源很多&#xff0c;例如&#xff1a;Kafka、Flume、Twitter、ZeroMQ和简单的TCP套接字等等。数据输入后可以用Spark的高度抽象原语如&#xff1a;map、…

鸿蒙南向开发—OpenHarmony技术编译构建框架

概述 OpenHarmony编译子系统是以GN和Ninja构建为基座&#xff0c;对构建和配置粒度进行部件化抽象、对内建模块进行功能增强、对业务模块进行功能扩展的系统&#xff0c;该系统提供以下基本功能&#xff1a; 以部件为最小粒度拼装产品和独立编译。支持轻量、小型、标准三种系…