Java二进制的加减乘除

    引子

    某天研究 fail-fast机制的时候,去看了看hashCode的实现方式,然后发现每个对象的实现都不一样;于是研究一个String的;于是看到公式:

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

于是很不解,这个公式很明显会溢出(超过2^32),尝试了几次发现系统会输出hashCode为负数的值,就默默地去回顾一下二进制的加减乘除


准备工作:

-2 = 0xfffffffe
-1 = 0xffffffff
0 = 0x0
1 = 0x1
2 = 0x2
max = 0x7fffffff = 2147483647
min = 0x80000000 = -2147483648
正数与二进制的相互转换,就是简单的二进制与十进制的相互转换
负数与二进制的相互转换:
1)二进制 -> 负数 :0x80000000  取反  0x7fffffff(2147483647)  忽略符号加一 (2147483648)  结果(- 2147483648 )
2)负数 -> 二进制 : - 2147483648 忽略符号减一(- 2147483647[ 0x7fffffff ])   取反( 0x80000000 ) 结果( 0x80000000 )
PS:以上就是专业术语"补码"的含义,而补码存在的意义在于:让所有的加法能够使用同一种电路完成


接下来就是四则运算:加减乘除
1,加法[全加器]
案例一:
3 + 5 = 8
==>
  0 0 1 1  -> 3
+ 0 1 0 1  -> 5
----------
= 1 0 0 0  -> 8
因此可以看出,二进制之间的加法就是,和小学学的十进制的"尾数相加,然后进位

案例二:
1 + -1(0x7fffffff) = 0
==>
 ?_ 0 0 ... 1  -> 1
+?_ 1 1 ... 1  -> -1
--------------
=1_ 0 0 ... 0  -> 0
因此可以看出,二进制之间的加法,最高位表示的不是具体的数值,进位之后应该被舍去

2,减法 [全加器]
减法可以实现的方案:1)类似十进制的减法直接去位 2)减法就是另类的加法
而计算机采用的是,方法2,原因:直接可以使用全加器

例如:a - b = a + (-b)
而通过之前的准备可以看出:二进制中,b的负数就是b的补码
因此,0xa - 0xb = 0xa + 0xb(补码[取反,忽略符号加一])

3,乘法[乘法器,芯片]
乘法可以实现方案:1) 类似十进制的乘法  2) 多个加法
而计算机采用的是,方法1,原因:多个加法的算法复杂度成二次方增长

案例一:
3 * 5 = 15
==>
0 0 1 1 -> 3
* 0 1 0 1 -> 5
-------------
0 1 0 1 -> 5
+ 0 1 0 1 -> 10
-------------
1 1 1 1 -> 15
PS:
1)如果有符号,符号位另算,即:同号得正,不同号得负原则
2)如果有位数移除,则高位直接舍去,然后得出剩下的二进制对应的值

4,除法[芯片]
除法可以实现方案:1)类似十进制的除法 2)多个减法,直到负数
而计算机采用的是,方法1,原因:多个减法的算法复杂的成二次方增长
14 / 3 = 4 余 2
14(1110[被除数])、3(11[除数])、4([结果])、2([余数])
==>
1 0 0 --> 结果[4]
-----------
1 1 / 1 1 1 0
---------------
1 1
---------------
0 1
---------------
1 0
---------------
1 0 --> 余数[2]
PS:
1)如果有符号,符号位另算, 即:同号得正,不同号得负原则

回顾之前的问题,公式溢出问题:

s[0]*31^(n-1) + s[1]*31^(n-2) + ... + s[n-1]

就很容易解释了,

1,31^(n-1)的结果,高位会被省去

2,加法结果的结果,高位会被省去,这也是为什么会计算出负数的原因




以下是一个基于Java GUI的简单计算器示例,具有加、减、乘、除、清屏和进制转换功能: ```java import javax.swing.*; import java.awt.*; import java.awt.event.*; public class Calculator extends JFrame implements ActionListener { private JTextField textField; private JButton button1, button2, button3, button4, button5, button6, button7, button8, button9, button0; private JButton add, subtract, multiply, divide, clear, convert; private int num1, num2; private String operator; public Calculator() { setTitle("Calculator"); setSize(400, 400); setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE); JPanel panel = new JPanel(); panel.setLayout(new GridLayout(4, 4)); textField = new JTextField(); add(textField, BorderLayout.NORTH); button1 = new JButton("1"); button2 = new JButton("2"); button3 = new JButton("3"); button4 = new JButton("4"); button5 = new JButton("5"); button6 = new JButton("6"); button7 = new JButton("7"); button8 = new JButton("8"); button9 = new JButton("9"); button0 = new JButton("0"); add = new JButton("+"); subtract = new JButton("-"); multiply = new JButton("*"); divide = new JButton("/"); clear = new JButton("C"); convert = new JButton("Convert"); panel.add(button1); panel.add(button2); panel.add(button3); panel.add(add); panel.add(button4); panel.add(button5); panel.add(button6); panel.add(subtract); panel.add(button7); panel.add(button8); panel.add(button9); panel.add(multiply); panel.add(clear); panel.add(button0); panel.add(convert); panel.add(divide); add(panel); button1.addActionListener(this); button2.addActionListener(this); button3.addActionListener(this); button4.addActionListener(this); button5.addActionListener(this); button6.addActionListener(this); button7.addActionListener(this); button8.addActionListener(this); button9.addActionListener(this); button0.addActionListener(this); add.addActionListener(this); subtract.addActionListener(this); multiply.addActionListener(this); divide.addActionListener(this); clear.addActionListener(this); convert.addActionListener(this); setVisible(true); } public void actionPerformed(ActionEvent e) { String command = e.getActionCommand(); if (command.equals("+")) { num1 = Integer.parseInt(textField.getText()); operator = "+"; textField.setText(""); } else if (command.equals("-")) { num1 = Integer.parseInt(textField.getText()); operator = "-"; textField.setText(""); } else if (command.equals("*")) { num1 = Integer.parseInt(textField.getText()); operator = "*"; textField.setText(""); } else if (command.equals("/")) { num1 = Integer.parseInt(textField.getText()); operator = "/"; textField.setText(""); } else if (command.equals("C")) { num1 = 0; num2 = 0; operator = ""; textField.setText(""); } else if (command.equals("Convert")) { num1 = Integer.parseInt(textField.getText()); textField.setText(Integer.toString(num1, 2)); } else { textField.setText(textField.getText() + command); } if (!operator.equals("")) { if (!textField.getText().equals("")) { num2 = Integer.parseInt(textField.getText()); } } if (command.equals("=")) { int result = 0; if (operator.equals("+")) { result = num1 + num2; } else if (operator.equals("-")) { result = num1 - num2; } else if (operator.equals("*")) { result = num1 * num2; } else if (operator.equals("/")) { result = num1 / num2; } textField.setText(Integer.toString(result)); num1 = result; num2 = 0; operator = ""; } } public static void main(String[] args) { new Calculator(); } } ``` 这个例子使用JFrame作为主窗口,JPanel包含所有的计算器按钮。在JPanel上设置了一个GridLayout布局,将所有的按钮放置在4行4列的网格中。 通过实现ActionListener接口,我们可以对按钮点击事件进行处理。我们在actionPerformed方法中判断哪个按钮被点击,并根据需要执行不同的操作。在这个例子中,我们使用了整数变量num1、num2和operator来存储计算过程中的值和操作符。 在Clear按钮的点击事件中,我们将所有变量重置为初始值。在Convert按钮的点击事件中,我们将用户输入的十进制数转换为二进制数并显示在文本框中。在运算符按钮的点击事件中,我们将用户输入的第一个数存储在num1中,并将操作符存储在operator中。在等于按钮的点击事件中,我们计算num1和num2的结果,并将结果显示在文本框中。 这只是一个简单的计算器示例,你可以根据自己的需要添加更多的按钮和功能,例如小数的加减乘除、科学计算等。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值