任意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 ...
随机推荐
- Newtonsoft.Json序列化Enum类型
[JsonConverter(typeof(StringEnumConverter))] public StringAlignment TextAlign { get => textAlign; ...
- 使用 Quartz.NET 实现作业串行执行
Ø 前言 前两天,在公司的一个项目中编写 Windows 服务时,需求是当A服务运行完后,B服务才能运行,B服务运行后,C服务才能运行.因为B服务的数据依赖于A服务生成的数据,而C服务的数据又依赖于 ...
- JS创建对象之稳妥构造函数模式
所谓稳妥对象,指的是没有公共属性,而且其方法也不引用this的对象 function Person(name, age, job) { // 创建要返回的对象 var o = new Object() ...
- Handy Collaborator :用于挖掘out-of-band类漏洞的Burp插件介绍
本文我将介绍一个新的 Burp Suite插件Handy Collaborator.Burp Suite Collaborator是添加到Burp Suite的外部服务器,主要用于挖掘那些仅来自外部服 ...
- 服务器上定时自动执行php
两种方式: 一.Linux 服务器Linux原生支持crontab,所以可以利用这一功能做定时任务 步骤: 1.编辑crontab文件:Linux:crontab -e 2.输入代码:0 0 * * ...
- 手动写Entity Framework 数据库上下文和Model实体
1.引用EF对应的程序集 使用命令安装EntityFramework包Install-Package EntityFramework Entity Framework简单目录: 1.context数据 ...
- c++ 回调函数封装
std::function<void(int a,int b)> ha; //函数封装 当成参数用callback std::bind(&fun1,this,std::plac ...
- 第27月第18天 epoll lt et
1. While the usage of epoll when employed as a level-triggered interface does have the same semantic ...
- 第26月第7天 mac如何matplotlib中文乱码问题
1.mac如何matplotlib中文乱码问题 先查看 ~/.matplotlib/fontList.json 添加SimHei字体(simhei.ttf文件)到 /Library/Framework ...
- 第21月第7日 数据结构 b+树
1.B+树 MySQL支持诸多存储引擎,而各种存储引擎对索引的支持也各不相同,因此MySQL数据库支持多种索引类型,如BTree索引,哈希索引,全文索引等等. http://blog.codingla ...