简易计算器1.0版本
该计算器中主要用到了java中的函数(方法),大数运算,Swing中的一些界面组件。
主要实现功能:数字输入,包含输入小数点和清除当前输入
数字计算(+,-,*,/,%,1/x)
设计主要内容:
1.数字输入:申请一个字符串NUM,设置为全局变量,当监听的事件为输入为数字时,调用函数(方法)向NUM字符串末尾添加输入数字的字符,当NUM字符串中只有一个字符0时,则直接将输入的当前数字的字符直接赋值给字符串NUM,防止在文本框中显示“0123”这种情况,对于每输入一个数字,就将构建好的字符串转换成double类型的一个数字存入全局变量num中记录。
2.数字清除:当监听的事件是清除数字时,将定义的全局变量num作为参数调入函数(方法),首先将该数字转换成字符串,然后首先判断字符串长度,如果字符串长度l为1,则表示清除1位数字后字符串内无字符,但是在文本框区域应当显示为0,所以此时让字符串str="0",
如果字符串长度l大于1,则让str=str.substring(0,l-1)(该方法是获取子符串),将字符串更新为原字符串的前l-1个字符,去掉最后一个字符。
3.归零功能:将数据全部初始化,用于开始一次新的计算。
4.小数点处理:当监听的事件为要输入小数点时,因为每次输入运算数据时都是直接在字符串末尾添加数据实现的,如果直接添加小数点会出现一个数字内含有多个小数点的错误情况,所以,在往数字字符串添加小数点时,首先调用indexOf()方法判断是否在数字字符串中出现过小数点,如果没有出现过,则在字符串末尾加上小数点,否则直接返回(注:当为空字符串时,如果首先输入小数点,字符串中数据会出现“.123”这种情况,所以应当加上判断:当为空字符串时,该字符串应该是在字符串末尾加上“0.”两个字符)。
5.数字计算:对于每次按键输入判断是什么计算符号,调用函数(方法),判断符合哪一种计算方式,带入进行计算,返回最终计算结果,如果输入的是等号时,需要判断是否下一次计算还需要当前结果,如果需要,保留当前计算结果,不符合则直接清空数据,初始化后进行下一次计算。
6.计算结果判断:对于每一次计算的结果,判断输出是整数还是小数形式输出,对于每一次输出都调用一次函数进行判断。
格式:1.按钮组件
2.文本组件,字符右对齐
3.一个JFrame窗口
4.设置1个6行1列的网格布局管理器
5.设置了6个JPanel面板,1个用于文本框,其余5个用于按钮
编写时遇到的部分解决的问题:
1.对于每一次运算的输入,都是数据+运算符+数据,对于计算机每接受一个运算符需要等待下一个数据输入才能进行计算。
解决方法:计算机每次需要接收下一个数据计算,那么可以将每次输入的式子转换成:运算符+数据+运算符+数据,这样处理后,如果输入一个运算符,则计算上一个输入的数据。
例如输入为:8+6-3=
计算方式为:+8+6-3=
计算器运行次序:首先输入一个8,当输入第一个加号时进行一次运算,进行第一次计算,让最终值sum+8输出结果,同时记录当前的加号,接下来输入6,然后输入“-”时,让sum+6,输出结果,这时的加号是之前所记录的运算符,接下来输入3,然后输入“=”,此时在进行一次计算,让终值sum-3,输出结果。总之,就是每当到来一个数据,然后根据这个数据之前的运算符进行一次计算。
2.完成一次计算时,如果需要当前计算的结果直接进行下一次计算,或者开始一次新的计算,对于之前保存或者清除的问题。
解决方法:判断一次等号输入之后,下一次输入时是数字还是运算符,如果是运算符时,保留之前运算的数据,用于继续计算,如果是数字,则调用归零函数,清空之前的运算数据。
3.运算时,输入完一个数字数据后,如果连续按了多次的运算符号,如何处理问题。
解决方法:添加一个标记变量,当输入时为数字数据时,该变量f赋值恒为0,并一直更新运算符标记变量flag,同时变量f++,这样,如果再次输入数字数据,按照解决问题1的思路,调用之前运算符标记变量flag所记录的最后一次标记结果进行计算即可。
未解决问题:
1.部分计算精度存在问题。
2.可能还存在部分bug,测试可能不够完善。
代码如下:
/*
* 计算器1.0版本
*/
package swing;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
import java.math.BigDecimal;
public class Calculator extends JFrame{
public static double sum=0;//存储每次计算的最终结果结果
public static double num=0;//存储输入结果
public static int flag=11;//标记计算器的运算符号
public static int F=0;//判断等号是否出现以及是否重置计算结果
public static int f=0;//记录运算符一次性输入次数,防止多此输入运算符导致计算逻辑出错
public static int F1=0;//1/x计算标记变量
public static String NUM="";//当输入数字和小数点按键时用于构建输入数据的字符串
private static final long serialVersionUID = 1L;
private static final String String = null;
//该函数永与判断输出在屏幕上的数字是否需要输出小数点之后的数字,对于整数计算结果,不需要输出小数点之后的数字
public static String Handle(String str){
int n=str.indexOf(".");//首先判断小数点是否存在,存在返回小数点检索参数,不存在返回-1
if(n!=-1)//小数点存在时
{
char [] s=str.toCharArray();//将字符串转换成字符数组逐个判断
for(int i=n+1;(i<s.length)&&(i<=20);i++)//因为屏幕显示长度为20个字符,所以最多只需要判断20位即可
{
char s1=s[i];
char s2='0';
if(s1!=s2)//判断小数点后是否存在非0字符
{
return str;//说明需要当前数字为double类型,返回整个字符串
}
}
return str.substring(0,n);//说明当前数字为int型,只返回整数部分
}
return str;//如果输入的是不含小数点的数字,返回原数字
}
public String Eliminate(String str) {//删除(←)
int l=str.length();//将输入的数字转换成字符串计算输入的数字长度
if(l<=1)//当输入数字长度为l=1时,清除一位在屏幕上显示应该是数字0
{
str="0";
}
else//当输入数字长度大于l>1时,将最后一位删除,将前l-1为重新存入字符串
{
str=str.substring(0,l-1);
}
return str;
}
public String Zero(String str) {//归零(c),对数据进行初始化
str="";
F1=0;
sum=0;
num=0;
flag=11;//在每次重新计算时将第一个输入的数字累加到存在最终结果的变量上
return str;
}
public String Number(String str,String s)//输入数字键(0-9)
{
if(str.equals("0"))//当输入被全部清除时,str内有一个“0”字符,再次输入需要把该字符覆盖
{
str=s;
}
else {
str=str+s;//将新输入的字符接到之前的数字末尾
}
return str;
}
public String DecimalPoint(String str)//输入小数点处理
{
int flag=str.indexOf(".");//判断当前输入数字中是否存在小数点
int l=str.length();
if(flag==-1)//如果不存在小数点添加小数点,否则直接返回当前值,防止添加多余的小数点
{
if(l==0)
{
str+="0";
}
str=str+".";
}
return str;
}
public void Operation(int flag)//六种运算和等号(+,-,*,/,%,1/x)
{
// System.out.println("flag="+flag);
// System.out.println("num="+num);
// System.out.println("sum="+sum);
// System.out.println("-----------------");
BigDecimal bigA = new BigDecimal(Double.toString(sum));
BigDecimal bigB = new BigDecimal(Double.toString(num));
if(flag==11)//加法
{
sum=bigA.add(bigB).doubleValue();
}
if(flag==12)//减法
{
sum=bigA.subtract(bigB).doubleValue();
}
if(flag==13)//乘法
{
sum=bigA.multiply(bigB).doubleValue();
}
if(flag==14)//除法
{
if(num==0)//当num等于0时属于不合法输入
{
NUM="输入错误:除数不能为0";//输出错误提示
return ;
}
sum=sum/num;
// sum=bigA.divide(bigB).doubleValue();
}
if(flag==15)//取余
{
sum=sum%num;
}
if(flag==17)//1/x运算
{
System.out.println("********"+F1);
if(F1==1)
{
if(num==0)
{
NUM="输入错误:除数不能为0";
return ;
}
sum=1/num;
}
else
{
if(sum==0)
{
NUM="输入错误:除数不能为0";
return ;
}
sum=1/sum;
}
}
NUM=String.valueOf(sum);
if(flag==16)//等号判断
{
NUM=String.valueOf(sum);
flag=11;
F=1;
NUM="0";//字符串置空
}
return ;
}
// public
public Calculator() {
//创建按键字符串
final String[] str= {"←","c","%","1/x","7","8","9","+","4","5","6","-","1","2","3","*","0",".","/","="};
//将每个按键编号,对动作进行判断
final int[] next = {18 ,19 ,15 , 17 , 7 , 8 , 9 , 11, 4 , 5 , 6 , 12, 1 , 2 , 3 ,13 , 0 , 10, 14 ,16};
setSize(300,400);//设置窗口大小
setTitle("计算器 1.0");
Container c=getContentPane();
c.setLayout(new GridLayout(6,1,5,5));//将容器设置成6行1列的网格布局
setDefaultCloseOperation(WindowConstants.DISPOSE_ON_CLOSE);//设置文本字体和大小
final JButton[] jb=new JButton[30];//创建按钮数字
final JTextField jt=new JTextField("",20 );//创建文本框
jt.setHorizontalAlignment(JTextField.RIGHT);//设置为右对齐
JPanel[] p=new JPanel[6];//创建JPanel面板数组
jt.setFont(new Font("宋体",Font.PLAIN,25));
JPanel p0=new JPanel(new GridLayout(1,1,5,5));//初始化面板p0,设置一个一行一列的网格布局,用于文本框
p0.add(jt);//添加文本框
for(int i=0;i<5;i++)//循环输出按钮
{
p[i]=new JPanel(new GridLayout(1,4,5,5));//初始化面板数组,将每个面板设置成1行4列,用于安放按钮
for(int j=0;j<4;j++)
{
final int n=i*4+j;//计算按键是第几个
jb[n]=new JButton(str[i*4+j]);//为按钮设置数字
jb[n].addActionListener(new ActionListener() {//按键事件监听
public void actionPerformed(ActionEvent e) {
// System.out.println("按键输入:"+n);
if(next[n]==18) {//消除
NUM=Eliminate(NUM);//调用清除函数
num=Double.parseDouble(NUM);//将String型数据转换成double型数据
jt.setText(Handle(NUM));
}
else if(next[n]==19)//归零
{
NUM=Zero(NUM);//调用归零函数
jt.setText("");//在文本显示区显示为空
}
else if(next[n]>=0&&next[n]<10)//数字键
{
if(F==1)
{
NUM=Zero(NUM);//调用归零函数
F=0;
F1=0;
}
f=0;
NUM=Number(NUM,str[n]);//调用数字输入函数
num=Double.parseDouble(NUM); //将String型数据转换成double型数据
jt.setText(Handle(NUM));//按字符串输出计算结果
}
else if(next[n]==10)//小数点
{
NUM=DecimalPoint(NUM);//调用添加小数点函数
num=Double.parseDouble(NUM);//将String型数据转换成double型数据
jt.setText(Handle(NUM));//按字符串输出计算结果
}
else if(next[n]>=11&&next[n]<=17)//运算
{
if(next[n]==16)//判断等号输入情况
{
F=1;//改变量用于判断每次计算结束后如何进行下一次计算
} //F=0表示新一次计算,等于1表示继续使用上一次计算结果
else
{
F=0;
}
jt.setText(Handle(String.valueOf(sum)));//按字符串输出计算结果
f++;//记录按键输入次数
F1++;//记录1/x输入次数,判断如何调用1/x运算
if(next[n]==17)//
{
Operation(17);//调用运算函数计算上一次运算符运算结果
jt.setText(Handle(NUM));
}
else if(f==1)
{
Operation(flag);//调用运算函数计算上一次运算符运算结果
jt.setText(Handle(NUM));//按字符串输出计算结果
}
flag=next[n];//记录当前输入的运算符
num=0;
NUM="";//重置
}
}
});
p[i].add(jb[n]);//向面板添加按钮
}
}
c.add(p0);//在容器中添加面板
for(int i=0;i<5;i++)
{
c.add(p[i]);//在容器中添加面板
}
setVisible(true);
}
public static void main(String[] args) {
new Calculator();
}
}
最后吐槽一下:改完一个问题,另一个又出现bug,脑壳痛........