任意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 ...
随机推荐
- web 安全知识点
XSS 新手指南:DVWA-1.9全级别教程(完结篇,附实例)之XSS https://www.jianshu.com/p/303206ae2471 https://www.netsparker.co ...
- Kaldi阅读并更改代码
Common utilities base/kaldi-common.h 几乎所有Kaldi程序都会include该头文件. 该头文件include了一些其他位于base/目录的头文件,主要提供: 错 ...
- Hbase思维导图之逻辑结构
- JSP动态页面技术
1.JSP和html的区别 处理过程的区别 HTML 浏览器发送一个请求到服务器,服务器找到这个页面直接返回. JSP 浏览器发送一个请求道服务器,服务器判断到时.jsp结尾,去调用JSP引擎,JSP ...
- JQ中的 offsetTop 和 offset().top 的区别
话不多说先上图: offset()的top是指元素与document的上边的距离,而不是浏览器当前窗体的上边缘,如图 document高度超过window,浏览器出现滚动条,滚动滚动条,提交按钮的of ...
- Maven项目配置logback
首先,在pom.xml中加入maven依赖 <!-- log start --> <dependency> <groupId>org.slf4j</group ...
- 【tmos】字段update_time如何动态的更新
1.数据库设置 2.数据库不设置,用Jpa的注解来完成 @EnableJpaAuditing注解 @SpringBootApplication @EnableJpaAuditing public cl ...
- windows10+ubuntu16.04双系统搭建
0 - 环境 操作系统: Windows 10 + Ubuntu 16.04 显卡: GTX 950M Cuda 9.0 cudnn v7.0 tensorflow-gpu==1.7.0 1 - ub ...
- Microsoft SQL - 查询与更新
查询与更新(Query & Update) 转义引号 SQL语句中字符串只能使用单引号,如果需要转义,可用单引号转义单引号. 查询(Inquire) 以下公式中的c指代列名. 规则 1.查询语 ...
- MySQL报错解决方案:2013-Lost connection
今天上课的时候,在搭建完MySQL测试环境中出现的问题,整理如下: 问题描述:搭建完MySQL,用远程连接工具(Navicat)连接时报错: 2013-Lost connection to MySQL ...