前面一篇提到二进制队列实现了 N位二进制的补码,那么我们来实现布思算法。

关于BinaryQueue:https://www.cnblogs.com/XT-xutao/p/10050518.html

先来思考:我们这样实现二进制乘法呢?

对于无符号整数,是可以转化为加法的:

那么补码形式呢?好像一些也是可以用上面这种转化为加法的:

上面被乘数-7是小于0的,但是乘数为负的时候好像就不能工作了,因为不能正确地得出部分积。

怎么办呢?

还有一种方法: 就是在乘之前先判断符号,如果异号,则结果为负,用他们的绝对值形式乘就可以了,最后加符号就行。

但是,这种方法似乎太麻烦了,我们更偏向于——布思算法(BOOTH)

布思算法是基于: 2^n+2^n-1......2^n-k  =  2^(n+1) - 2^(n-k)

它有两大优点:

1.避免了如上的那种复杂操作。

2.减少了不必要的加法,节约了时间。

那么在计算机底层是怎么实现的呢?

可以用几个寄存器搞定:

A:附加寄存器,初始化0

Q:乘数寄存器

M:被乘数寄存器

Q0:乘数的最低位,初始化0

根据流程图就可以实现了。最后的结果是AQ寄存器里的值。

更新:前面讲那个BinaryQueue方法不好,直接用字符串形式的二进制表示更简单:
     public String multiply(String Q,String M){
char Q0 = '0';
String A = get01(Q.length(),"0");
for (int i=0;i<Q.length();i++){
String QQ0 =Q.charAt(Q.length()-1)+""+Q0;//不能把两个char字符放在一起,会变成加
System.out.println(QQ0);
if (QQ0.equals("10")){
A=substract(A,M).substring(1);
}
else if (QQ0.equals("01")){
A=add(A,M).substring(1);
}
String temp = shiftRight(A+Q+Q0);
A=temp.substring(0,A.length());
Q = temp.substring(A.length(),2*A.length());
Q0 = temp.charAt(temp.length()-1);
}
return A+Q;
}

那么代码怎么实现(BinaryQueue)呢?

 package com.computerOrganizationAndArchitecture.IntegerOperation;

 import com.computerOrganizationAndArchitecture.BinaryQueue;

 /**
* Created by XuTao on 2018/12/1 19:27
* 用BinaryQueue实现布思算法 (Java语言)
*/
public class Booth {
BinaryQueue Q, M, A; // Q:乘数; M:被乘数; A: 附加
private String n1,n2;
public Booth(String str1, String str2) {//要进行操作的两个二进制数的字符串模式
this.n1=str1;
this.n2=str2;
int len; // 最长的长度(如果两个二进制不一样长的话)
//扩展短的那个
if (n1.length() > n2.length()) {
String s = "";
len = n1.length() - n2.length();
for (int i = 0; i < len; i++) {
s += n2.charAt(0);
}
n2 = s + n2;
}
else if (n1.length()<n2.length()){
String s = "";
len = n2.length() - n1.length();
for (int i = 0; i < len; i++) {
s += n1.charAt(0);
}
n1 = s + n1;
System.out.println(n1);
}
else len = n1.length(); Q = new BinaryQueue(n1);
M = new BinaryQueue(n2);
A = new BinaryQueue(len);
int Q0 = 0; //Q的最低位,初始化为0,用于判断要进行的操作 System.out.println(A.getStr() + " " + Q.getStr() + " " + Q0 + " " + M.getStr());
for (int i = 0; i < len; i++) {
if (Q.getLast() == 1 && Q0 == 0) {//1-0 模式,A= A-M,
A = A.subtract(M);
} else if (Q.getLast() == 0 && Q0 == 1) {
A = A.add(M);
}
//AQQ0右移一位
Q0 = Q.getLast();
Q.shiftRight();
Q.set(0, A.getLast());
A.shiftRightArithmetically(); System.out.println(A.getStr() + " " + Q.getStr() + " " + Q0 + " " + M.getStr());
}
BinaryQueue bq = new BinaryQueue(A.getStr() + Q.getStr());// A + Q
System.out.println(A.getStr() + Q.getStr());
System.out.println(bq.getInt());
} public static void main(String[] args) {
new Booth("0011", "1111"); //3 * -1 = -3
new Booth("111111", "001111"); //-1 * 15 = -15
new Booth("011110", "001111"); //30 * 15 = 450
} } demo: A Q Q0 M

0000 0011 0 1111   第0周期
0000 1001 1 1111   第1周期
0000 0100 1 1111   第2周期
1111 1010 0 1111   第3周期
1111 1101 0 1111   第4周期

结果:

11111101

-3


000000 111111 0 001111
111000 111111 1 001111
111100 011111 1 001111
111110 001111 1 001111
111111 000111 1 001111
111111 100011 1 001111
111111 110001 1 001111
111111110001
-15


000000 011110 0 001111
000000 001111 0 001111
111000 100111 1 001111
111100 010011 1 001111
111110 001001 1 001111
111111 000100 1 001111
000111 000010 0 001111
000111000010
450

 

布思算法——Java实现的更多相关文章

  1. 布思算法Java实现

    public String multiply(String Q,String M){ char Q0 = '0'; String A = get01(Q.length(),"0") ...

  2. Spark案例分析

    一.需求:计算网页访问量前三名 import org.apache.spark.rdd.RDD import org.apache.spark.{SparkConf, SparkContext} /* ...

  3. 二进制补码除法——计算机底层整数除法模拟之Java实现

    前面讲到布思算法的计算机底层模拟的时候,我们是借助于一个可以储存.表示任意N位的二进制补码的BinaryQueue实现的,现在我们模拟计算机底层整数除法还是要借助于它: BinaryQueue类代码: ...

  4. 故障重现(内存篇2),JAVA内存不足导致频繁回收和swap引起的性能问题

    背景起因: 记起以前的另一次也是关于内存的调优分享下   有个系统平时运行非常稳定运行(没经历过大并发考验),然而在一次活动后,人数并发一上来后,系统开始卡. 我按经验开始调优,在每个关键步骤的加入如 ...

  5. Elasticsearch之java的基本操作一

    摘要   接触ElasticSearch已经有一段了.在这期间,遇到很多问题,但在最后自己的不断探索下解决了这些问题.看到网上或多或少的都有一些介绍ElasticSearch相关知识的文档,但个人觉得 ...

  6. 论:开发者信仰之“天下IT是一家“(Java .NET篇)

    比尔盖茨公认的IT界领军人物,打造了辉煌一时的PC时代. 2008年,史蒂夫鲍尔默接替了盖茨的工作,成为微软公司的总裁. 2013年他与微软做了最后的道别. 2013年以后,我才真正看到了微软的变化. ...

  7. 故障重现, JAVA进程内存不够时突然挂掉模拟

    背景,服务器上的一个JAVA服务进程突然挂掉,查看产生了崩溃日志,如下: # Set larger code cache with -XX:ReservedCodeCacheSize= # This ...

  8. 死磕内存篇 --- JAVA进程和linux内存间的大小关系

    运行个JAVA 用sleep去hold住 package org.hjb.test; public class TestOnly { public static void main(String[] ...

  9. 【小程序分享篇 一 】开发了个JAVA小程序, 用于清除内存卡或者U盘里的垃圾文件非常有用

    有一种场景, 手机内存卡空间被用光了,但又不知道哪个文件占用了太大,一个个文件夹去找又太麻烦,所以我开发了个小程序把手机所有文件(包括路径下所有层次子文件夹下的文件)进行一个排序,这样你就可以找出哪个 ...

随机推荐

  1. SDL 库 无法解析的外部符号 __imp__fprintf

    VS2015 在链接器->命令行 里加入legacy_stdio_definitions.lib 另外一个常见错误关于stderr的用 extern "C" { FILE _ ...

  2. From 192.168.25.133 icmp_seq=238 Destination Host Unreachable 虚拟机ping主机不通

    From 192.168.25.133 icmp_seq=238 Destination Host Unreachable 虚拟机ping主机不通,但是主机可以ping通虚拟机,虚拟机ping不通外网 ...

  3. 关于TCP/IOCP构架中出现的Socket假死连接解决方案

    如果在2台不同的公网机器,对TCP的c/s做过详细的压力测试,那么很不幸,会有很多人发现自己的server端会出现大量的假死连接. 假死连接具体表现如下: 1.在s端机器上,会有一些处于TCP_EST ...

  4. JS算法练习四

    JS算法练习 1.将使用空格分隔单词使用驼峰命名连接起来: var str="HELLO world welcome to my hometown"; /*--先输入一个有空格分隔 ...

  5. class按传递时分析

    class FEF{ public: int a; FEF(int a,int b){ this->a = a*b; } }; void mam(FEF a){ printf("%d ...

  6. luogu P3175 [HAOI2015]按位或

    传送门 如果每个位置上的数字的意义是这个位置被加进集合的最早时间,那么我们要求的就是集合中最大数的期望,使用Min-Max容斥,\(E(max(S))=\sum_{T\subset S}(-1)^{| ...

  7. js判断浏览器类型和版本

    原网址:http://www.cnblogs.com/rubylouvre/archive/2009/10/14/1583362.html 除了另无它法,肯定不使用navigator.userAgen ...

  8. [转] Linux shell判断文件和文件夹是否存在

    shell判断文件,目录是否存在或者具有权限 #!/bin/sh myPath="/var/log/httpd/" myFile="/var /log/httpd/acc ...

  9. Python 19 Django 详解

    本节概要 Django详解 前言 有一部分原因是,确实djando的课程有点多:并且,最近又在研究利用python做数据分析时间上耽误了.所以楼主讲所有的课程全部重新观看了一遍,再来撰写博客,其实说起 ...

  10. HashSet去除List重复元素

    使用Hashset 去重复 例一,List<String> 去重复 public class main { public static void main(String[] args) { ...