zoukankan      html  css  js  c++  java
  • 任意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位补码二进制数,那么我们可以实现一些计算机底层的模拟了,比如布思算法等等。
  • 相关阅读:
    半截水晶头线接激活本地虚拟网卡
    快捷键
    嵌入式系统原理与应用技术(第三版)-读书笔记
    嵌入式基本常识(一)
    PWM输出
    ARM-GPIO
    POI使用
    oracle常见命令
    JS获取contextPath的方法
    JPA自动生成表
  • 原文地址:https://www.cnblogs.com/XT-xutao/p/10050518.html
Copyright © 2011-2022 走看看