任意N位二进制的补码实现——队列存放
正在学习计算机组织与结构,为了写一些底层的算术操作模拟,比如一个二进制补码数的加减乘除,发现这很麻烦,因为不管是什么语言,都只提供了8位、32、64位等部分位数的补码形式,那么怎么实现任意任意位的补码整数呢,由于我们不能利用现有的如Byte、Integer类,所以我们需要一个容器来存储我们自己编写的任意位的补码整数。
数组可以实现,但是数组移位可能比较麻烦,比如如果要实现二进制数的算术右移,必须要移动大部分元素。可以使用链表,虽然获取二进制数某一位的值比较麻烦,但是还是比数组可能更好一点。于是,我们采用基于链表的队列。
/**
* Created by XuTao on 2018/12/1 15:26
* 作用:存储一个n位二进制数,并实现左右移动、取反、求值等操作
/
public class BinaryQueue {
private int size; //二进制的位数
public Node head = new Node(-1); //head只是一个头节点,后面才是二进制数,从左到右,从高位到低位的
public BinaryQueue(int size){ //创建一个size大小的二进制,他被初始化为00000..00
this.size = size;
Node temp =head;
for (int i =0;i<size;i++){
temp .next = new Node(0);
temp = temp.next;
}
} public BinaryQueue(String binary){ //以二进制数创建
this.size = binary.length();
Node temp =head;
for (int i =0;i<size;i++){
temp .next = new Node(binary.charAt(i)-'0');
temp = temp.next;
}
} public void shiftLeft(){ //左移
head.next = head.next.next;
Node temp = head.next;
for (int i=0;i<size;i++){
if (i==size-2) {
temp.next = new Node(0);
break;
}
temp = temp.next;
}
} public void shiftRight(){//右移
Node first = head.next;
head.next = new Node(0);
head.next.next=first; Node temp = head;
for (int i =0;i<size;i++){
temp = temp.next;
}
temp.next =null;
} public void shiftRightArithmetically(){ //算术右移,符号扩展
Node first = head.next;
head.next = new Node(first.value);
head.next.next=first; Node temp = head;
for (int i =0;i<size;i++){
temp = temp.next;
}
temp.next =null;
} public BinaryQueue reverse(){//按引用传递,会改变值
BinaryQueue bq = new BinaryQueue(this.getStr()); // 重新建立一个,不改变原来的二进制
Node temp = bq.head.next;
for (int i =0;i<bq.size;i++){
temp.value = 1-temp.value; //取反,是1,1-1=0;是0:1-0=1
temp = temp.next;
}
return bq;
} public BinaryQueue add(BinaryQueue bq){
//将两个队列中的二进制放入数组中,如果长度不同则需要将短的进行算术扩展,
int len = bq.size>size?bq.size:size;
int [] arr_bq = new int[len];
int [] arr_this = new int[len];
if (bq.size>size){//bq 长,this扩展
String s = bq.getStr();
for (int i =0;i<len;i++){
arr_bq[i] = s.charAt(i)-'0';
}
String s_this = getStr();
for (int j =0 ;j<len;j++){
if (j<len-size){
arr_this[j] = head.next.value;
}
else {
arr_this[j]= s_this.charAt(j-(len-size))-'0';
}
}
}
else { //this 长 ,bq扩展
String s = this.getStr();
for (int i =0;i<len;i++){
arr_this[i] = s.charAt(i)-'0';
}
String s_bq = bq.getStr();
for (int j =0 ;j<len;j++){
if (j<len-size){
arr_bq[j] = bq.head.next.value;
}
else {
arr_bq[j]= s_bq.charAt(j-(len-size))-'0';
}
}
} //相加
int []res = new int[len];
int carry = 0; //上一次加的进位
for (int i = len-1;i>=0;i--){
res[i] = arr_bq[i]+arr_this[i]+carry;
if (res[i]==2){//进位1,本位0
res[i]=0;
carry =1;
}
else if (res[i]==3){//进位1,本位1
res[i]=1;
carry =1;
}
else carry = 0;
}
String str = "";
for (int i =0;i<len;i++){
str+=res[i];
}
return new BinaryQueue(str);
} public BinaryQueue subtract(BinaryQueue bq){ //减法
return this.add(bq.getOppositeNumber());//基于加法
} public BinaryQueue getOppositeNumber(){//取相反数,就是取反加一
String s = "";
for (int i=0;i<size-1;i++){
s+="0";
}
s+="1";
return reverse().add(new BinaryQueue(s));//加一
} public int getInt(){ //获取二进制所代表的补码整数
if (head.next.value==1){
return -Integer.valueOf(getOppositeNumber().getStr(),2);
}
return Integer.valueOf(getStr(),2);
} public void set(int index,int value){ //改变某一位
Node temp = head.next;
for (int i = 0;i<size;i++){
if (i==index)break;
temp = temp.next;
}
temp.value = value;
} public String getStr(){ //获取二进制字符形式
String str ="";
Node temp = head.next;
while (temp!=null){
str+=temp.value;
temp =temp.next;
}
return str;
} public int getLast(){ //获取最低位
Node temp = head;
for (int i = 0;i<size;i++){
temp = temp.next;
}
return temp.value;
} public static void main(String[] args) {
BinaryQueue bq = new BinaryQueue("1000000011");
BinaryQueue bq2 = new BinaryQueue("0000000001");
// System.out.println(bq.add(bq2).getStr());
System.out.println(bq2.getOppositeNumber().getStr());
// System.out.println(bq.getInt());
// System.out.println(bq2.getInt());
// System.out.println(bq.subtract(bq2).getInt());
System.out.println(bq.subtract(bq2).getInt());
} //节点类 }
class Node{
int value;
Node next;
Node (int value){
this.value = value;
} public int getValue() {
return value;
}
}
有了我们自己定义的任意的N位补码二进制数,那么我们可以实现一些计算机底层的模拟了,比如布思算法等等。
任意N位二进制的补码实现——队列存放的更多相关文章
- 将32位MD5摘要串转换为128位二进制字符串
将32为MD5摘要串转换为128位二进制字符串: /// <summary> /// 将字符串转成二进制 /// </summary> /// <param name=& ...
- (一一五)利用NSKeyedArchiver实现任意对象转为二进制
[应用背景] 在数据库中存储数据时,如果对象过于复杂,又不必要创建复杂的表,可以直接把整个对象转化为二进制存入数据库字段,然后取出后再还原即可. [实现方法] 在PHP中,使用序列化和反序列化可以实现 ...
- python实现IP地址转换为32位二进制
python实现IP地址转换为32位二进制 #!/usr/bin/env python # -*- coding:utf-8 -*- class IpAddrConverter(object): de ...
- 将两个byte型拼接成16位二进制,再转化为十进制
short s = 0; //一个16位整形变量,初值为 0000 0000 0000 0000 byte b1 = 1; //一个byte的变量,作为转换后的高8位,假设初值为 0000 0001 ...
- 32位二进制IP地址与十进制IP地址互相转换
代码: import java.util.List; import java.util.ArrayList; import java.util.Scanner; public class Transf ...
- 将IP地址字符串转为32位二进制
def str2bin(s): temp = s.split('.') result = '' for i in range(len(temp)): temp[i] = str(bin(int(tem ...
- RabbitMQ集群下队列存放消息的问题
RabbitMQ中队列有两种模式 1.默认 Default 2.镜像 Mirror [类似于mongoDB,从一直在通过主的操作日志来进行同步] *如果将队列定义为镜像模式,那么这个队列也将区分主从, ...
- Java的位运算符与二进制转换
转换: Java整型数据类型有:byte.char.short.int.long.要把它们转换成二进制的原码形式,必须明白他们各占几个字节.,一个字节==8位数 数据类型 ...
- 布思算法——Java实现
前面一篇提到二进制队列实现了 N位二进制的补码,那么我们来实现布思算法. 关于BinaryQueue:https://www.cnblogs.com/XT-xutao/p/10050518.html ...
随机推荐
- C++ vector和list的主要用法区别
vector可以直接通过下标访问,list不可以 1.vector ; i < userTypes.size(); i++) { str = userTypes[i].typeName; } 2 ...
- Android手机特殊软件配置
1. 安装360一键root http://root.360.cn/ 2.安装SSHdroid 用于启用手机的ssh 地址:https://www.apk20.com/apk/77332/v/7346 ...
- verilog仿真文件编写
verilog仿真文件大概框架: ·timescale 1ns/1ps //但需要时间 module xxx_tb(); //仿真文件不需要输入和输出, intput clk; ] xx; //根据需 ...
- UE4 位置转换相关函数
get mouse positionget mouse position scaled by dpiget viewport scaleDeproject Scence to WorldLocal T ...
- ue4 socket
Socket 地址: TSharedRef<FInternetAddr> internetAddr = ISocketSubsystem::Get(PLATFORM_SOCKETSUBSY ...
- CF920E Connected Components?
CF luogu 先讲两个靠谱的做法 1.首先因为有n个点,m条不存在的边,所以至少存在一个点,和m/n个点之间没边,所以把这个点找出来,连一下其他相连的点,这样还剩m/n个点没确定在哪个联通块,而这 ...
- 【blog】Markdown的css样式推荐
参考博客 分享一款Markdown的css样式:https://www.cnblogs.com/zhangjk1993/p/5442676.html 美化Markdown输出的HTML文档:http: ...
- 找出程序GasMileage中的哪一行与下列叙述相对应:
找出程序GasMileage中的哪一行与下列叙述相对应: a.通知程序将使用Scanner类 import java.util.Scannner; b.创建一个Scanner类的对象 Scan ...
- Android视频压缩
最推荐(使用方便,默认压缩为原来视频大小的1/4左右): https://blog.csdn.net/qq_35373333/article/details/79564991 https://git ...
- vue 中通过 ajax 获取数据时,如何避免绑定的数据中出现 property of undefined 错误
参考链接:https://segmentfault.com/q/1010000008264089?_ea=1597485