Java项目实战—多功能计算器设计与实现
一、应用概述
计算器应用是一个具有基本计算和科学计算功能的工具,包含图形用户界面(GUI),方便用户进行各种数学运算。
二、界面布局
1. 主面板
- 包含一个用于显示输入和结果的文本框,以及一个按钮面板。
- 按钮面板采用
GridLayout
布局,分为6行7列,包含数字按钮(0 - 9)、小数点按钮(.)、运算符按钮(+、-、*、/)、括号按钮((、))、功能按钮(如C、=、1/X、X!、√等)以及一些特殊函数按钮(sin、cos、tan、ln、log等)。
2. 辅助面板
- 包含“历史记录”和“内存”两个按钮,以及对应的显示区域。
- 点击“历史记录”按钮可查看之前的运算记录,点击“内存”按钮可查看内存相关操作的记录。
三、基本操作
1. 数字输入
- 直接点击数字按钮(0 - 9)即可输入数字。
- 如果当前输入框为空,点击小数点按钮(.)会输入“0.”。
- 如果当前输入的最后一个字符是运算符,点击小数点按钮(.)会在数字后添加小数点(例如输入“5 +.”会得到“5 + 0.”)。
- 如果当前输入的最后一个字符是数字且不包含小数点,点击小数点按钮(.)会直接在数字后添加小数点(例如输入“5.”会得到“5.”)。
2. 运算符输入
- 点击运算符按钮(+、-、*、/)可输入相应的运算符。
- 如果当前输入框为空且点击减号按钮(-),会直接输入负号。
- 如果当前输入的最后一个字符是数字、右括号、函数符号(如sin、cos等)或其他特定字符(如π、e、%),点击运算符按钮会在后面添加相应的运算符。
3. 括号输入
- 点击括号按钮((、))可输入括号。括号的使用遵循数学运算的优先级规则,计算器会自动处理括号内的运算。
4. 清除操作
- 点击“C”按钮可清空当前输入框中的内容,包括运算过程和结果。
5. 计算结果
- 点击“=”按钮可计算并显示结果。
- 如果之前已经进行过一次计算,再次点击“=”按钮会基于上一次的结果和新输入的内容进行计算。
四、科学计算操作
1. 三角函数计算
- 点击“sin”、“cos”、“tan”按钮可进行相应的三角函数计算。
- 在输入三角函数参数时,需先输入参数值,再点击相应的三角函数按钮(例如输入“30 sin”会计算30度的正弦值)。
- 可以通过点击“Deg”或“Rad”按钮切换三角函数的计算角度制和弧度制。默认以角度制进行计算。
2. 幂运算
- 点击“x的平方”(x²)、“x的三次方”(x³)、“x的y次方”(x^y)按钮可进行幂运算。
- 对于“x的y次方”按钮,输入底数后点击该按钮,再输入指数,最后点击“=”按钮计算结果。
3. 对数运算
- 点击“ln”(自然对数)和“log”(常用对数)按钮可进行对数运算。
- 输入对数的真数后,点击相应的对数按钮,再点击“=”按钮计算结果。
4. 阶乘运算
- 输入一个非负整数后,点击“X!”按钮可计算该数的阶乘。
5. 开方运算
- 点击“√”按钮可进行开平方运算,输入被开方数后点击该按钮,再点击“=”按钮计算结果。
- 点击“x开y次方”按钮可进行更复杂的开方运算,输入底数后点击该按钮,再输入指数,最后点击“=”按钮计算结果。
五、内存操作
1. 保存到内存
- 点击“ms”按钮可将当前计算结果保存到内存中。
2. 从内存读取
- 点击“mr”按钮可将内存中的值读取到当前输入框中。
3. 内存加法
- 点击“m+”按钮可将当前计算结果与内存中的值相加,并将结果保存到内存中。
4. 内存减法
- 点击“m-”按钮可将内存中的值减去当前计算结果,并将结果保存到内存中。
5. 清除内存
- 点击“mc”按钮可清空内存中的值。
六、其他功能
1. 历史记录查看
- 点击“历史记录”按钮可查看之前的运算记录,记录会显示输入的表达式和对应的计算结果。
2. 输入修正
- 点击“←”按钮可删除当前输入框中最后一个字符。
七、完整代码
1. BaseCalcuator
类
- 功能概述
- 该类提供了基本的数学运算功能,包括对加、减、乘、除以及括号的处理。
- 关键方法
replaceAllBlank
:去除字符串中的所有空白字符。isNumber
:判断字符串是否为数字。isSymbol
:判断字符串是否为运算符。calcLevel
:确定运算符的优先级。doMatch
:将输入的数学表达式字符串转换为后缀表达式形式的列表,同时处理运算符的优先级和括号。doCalc
:根据后缀表达式列表计算结果。doTheMath
:执行具体的数学运算(加、减、乘、除)。
import java.util.*;
import java.util.regex.Pattern;
public class BaseCalcuator {
/**
* 匹配 + - * / ( ) 运算符
*/
static final String SYMBOL = "\\+|-|\\*|/|\\(|\\)";
static final String LEFT = "(";
static final String RIGHT = ")";
static final String ADD = "+";
static final String MINUS = "-";
static final String TIMES = "*";
static final String DIVISION = "/";
static List<String> result;
String restult;
String math;
/**
* 加減 + -
*/
static final int LEVEL_01 = 1;
/**
* 乘除 * /
*/
static final int LEVEL_02 = 2;
/**
* 括号
*/
static final int LEVEL_HIGH = Integer.MAX_VALUE;
static Stack<String> stack = new Stack<>();
static List<String> data = Collections.synchronizedList(new ArrayList<String>());
/**
* 去除所有空白符
*
* @param s
* @return
*/
public static String replaceAllBlank(String s) {
// \\s+ 匹配任何空白字符,包括空格、制表符、换页符等等, 等价于[ \f\n\r\t\v]
return s.replaceAll("\\s+", "");
}
/**
* 判断是不是数字 int double long float
*
* @param s
* @return
*/
public static boolean isNumber(String s) {
Pattern pattern = Pattern.compile("^[-\\+]?[.\\d]*$");
return pattern.matcher(s).matches();
}
/**
* 判断是不是运算符
*
* @param s
* @return
*/
public static boolean isSymbol(String s) {
return s.matches(SYMBOL);
}
/**
* 匹配运算等级
*
* @param s
* @return
*/
public static int calcLevel(String s) {
if ("+".equals(s) || "-".equals(s)) {
return LEVEL_01;
} else if ("*".equals(s) || "/".equals(s)) {
return LEVEL_02;
}
return LEVEL_HIGH;
}
/**
* 匹配
*
* @param s
* @throws Exception
*/
public static List<String> doMatch(String s) throws Exception {
if (s == null || "".equals(s.trim()))
throw new RuntimeException("data is empty");
if (!isNumber(s.charAt(0) + ""))
throw new RuntimeException("data illeagle,start not with a number");
s = replaceAllBlank(s);
String each;
int start = 0;
for (int i = 0; i < s.length(); i++) {
if (isSymbol(s.charAt(i) + "")) {
each = s.charAt(i) + "";
// 栈为空,(操作符,或者 操作符优先级大于栈顶优先级 && 操作符优先级不是( )的优先级 及是 ) 不能直接入栈
if (stack.isEmpty() || LEFT.equals(each)
|| ((calcLevel(each) > calcLevel(stack.peek())) && calcLevel(each) < LEVEL_HIGH)) {
stack.push(each);
} else if (!stack.isEmpty() && calcLevel(each) <= calcLevel(stack.peek())) {
// 栈非空,操作符优先级小于等于栈顶优先级时出栈入列,直到栈为空,或者遇到了(,最后操作符入栈
while (!stack.isEmpty() && calcLevel(each) <= calcLevel(stack.peek())) {
if (calcLevel(stack.peek()) == LEVEL_HIGH) {
break;
}
data.add(stack.pop());
}
stack.push(each);
} else if (RIGHT.equals(each)) {
// ) 操作符,依次出栈入列直到空栈或者遇到了第一个)操作符,此时)出栈
while (!stack.isEmpty() && LEVEL_HIGH >= calcLevel(stack.peek())) {
if (LEVEL_HIGH == calcLevel(stack.peek())) {
stack.pop();
break;
}
data.add(stack.pop());
}
}
start = i; // 前一个运算符的位置
} else if (i == s.length() - 1 || isSymbol(s.charAt(i + 1) + "")) {
each = start == 0 ? s.substring(start, i + 1) : s.substring(start + 1, i + 1);
if (isNumber(each)) {
data.add(each);
continue;
}
throw new RuntimeException("data not match number");
}
}
// 如果栈里还有元素,此时元素需要依次出栈入列,可以想象栈里剩下栈顶为/,栈底为+,应该依次出栈入列,可以直接翻转整个stack 添加到队列
Collections.reverse(stack);
data.addAll(new ArrayList<>(stack));
// System.out.println(data);
return data;
}
/**
* 算出结果
*
* @param list
* @return
*/
public static Double doCalc(List<String> list) {
Double d = 0.0;
if (list == null || list.isEmpty()) {
return null;
}
if (list.size() == 1) {
result = list;
d = Double.valueOf(list.get(0));
return d;
}
ArrayList<String> list1 = new ArrayList<>();
for (int i = 0; i < list.size(); i++) {
list1.add(list.get(i));
if (isSymbol(list.get(i))) {
Double d1 = doTheMath(list.get(i - 2), list.get(i - 1), list.get(i));
list1.remove(i);
list1.remove(i - 1);
list1.set(i - 2, d1 + "");
list1.addAll(list.subList(i + 1, list.size()));
break;
}
}
doCalc(list1);
return d;
}
/**
* 运算
*
* @param s1
* @param s2
* @param symbol
* @return
*/
public static Double doTheMath(String s1, String s2, String symbol) {
Double result = 0.0;
switch (symbol) {
case ADD:
result = Double.valueOf(s1) + Double.valueOf(s2);
break;
case MINUS:
result = Double.valueOf(s1) - Double.valueOf(s2);
break;
case TIMES:
result = Double.valueOf(s1) * Double.valueOf(s2);
break;
case DIVISION:
if (Double.valueOf(s2) == 0) {
result = null;
break;
} else
result = Double.valueOf(s1) / Double.valueOf(s2);
break;
default:
result = null;
}
return result;
}
void fCalcuate() {
try {
// 开头为负得处理
if (math.charAt(0) == '-')
math = "0" + math;
// 处理开头为括号
if (math.charAt(0) == '(')
math = "0+" + math;
doCalc(doMatch(math));
restult = result.get(0);
} catch (Exception e) {
e.printStackTrace();
}
}
}
2. Calcuator
类
- 功能概述
- 该类是计算器的图形用户界面(GUI)实现,继承自
JFrame
并实现了ActionListener
接口,用于处理用户的输入和操作。
- 该类是计算器的图形用户界面(GUI)实现,继承自
- 关键成员变量
- 各种按钮(如数字按钮、运算符按钮、功能按钮等)以及对应的图标。
- 用于显示输入和结果的文本框。
- 存储运算过程和结果的字符串变量。
- 用于判断是否需要清空当前运算的标志变量。
- 用于存储三角函数计算方式的变量。
- 关键方法
- 构造函数:设置计算器的窗口属性、布局以及添加各种组件和按钮监听器。
createPanel1
和createPanel2
:分别创建计算器的主要面板和辅助面板(包含历史记录和内存相关功能)。actionPerformed
:处理按钮的点击事件,根据不同的按钮操作执行相应的逻辑,如输入数字、运算符,调用函数计算结果,处理内存操作等。- 一系列以
f
开头的方法(如fc
、fms
、fmr
等):用于实现具体的功能操作,如清空输入、保存到内存、从内存读取等。
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
//进行界面显示并添加监听
public class Calcuator extends JFrame implements ActionListener {
// 创建用于输入的文本框
TextArea text = new TextArea("", 2, 10, TextArea.SCROLLBARS_HORIZONTAL_ONLY);
// 卡片布局模板及其控制按钮的创建
JPanel CardPanel = new JPanel();
CardLayout cards = new CardLayout();
JButton record = new JButton("历史记录");
JButton mermory = new JButton(" 内存 ");
String ReSetrecordArea = "历史记录\n三角函数默认以角度制进行计算";
TextArea recordArea = new TextArea(ReSetrecordArea, 37, 26);
TextArea mermoryArea = new TextArea("内存", 37, 26);
// 存储运算过程
String mathPast = "";// 用于存储过去的运算过程
String mathNow = "";// 用于存储现在的运算过程
String showNow = "";
// 创建存储变量
private String m;
private String result = "";
String temp = "";// 用于暂时保留数字
// 用于判断是否需要清空mathNow进行新的运算
private int equal_flag = 0;
// 存储三角函数计算的方式,0为角度制,1为弧度制
private int TrigCalculMethod = 0;
// 创建x的平方,x的三次方,x的y次方,x开y次方按钮
ImageIcon squareimg = new ImageIcon("src\\Calcuator\\x的平方.png");// 创建图片对象
ImageIcon cubeimg = new ImageIcon("src\\Calcuator\\x的三次方.png");// 创建图片对象
ImageIcon powerimg = new ImageIcon("src\\Calcuator\\x的y次方.png");// 创建图片对象
ImageIcon readicationimg = new ImageIcon("src\\Calcuator\\x开y次方.png");// 创建图片对象
Image squareimage = squareimg.getImage();
Image cubeimage = cubeimg.getImage();
Image powerimage = powerimg.getImage();
Image readicationimage = readicationimg.getImage();
// 为把它缩小点,先要取出这个Icon的image ,然后缩放到合适的大小
Image squaresmallImage = squareimage.getScaledInstance(25, 25, Image.SCALE_FAST);
Image cubesmallImage = cubeimage.getScaledInstance(25, 25, Image.SCALE_FAST);
Image powersmallImage = powerimage.getScaledInstance(25, 25, Image.SCALE_FAST);
Image readictionsmallImage = readicationimage.getScaledInstance(30, 30, Image.SCALE_FAST);
// 再由修改后的Image来生成合适的Icon;
// ***Image对象创建ImageIcon对象,可查阅ImageIcon的构造方法***
ImageIcon smallIcon = new ImageIcon(squaresmallImage);
ImageIcon cmallIcon = new ImageIcon(cubesmallImage);
ImageIcon pmallIcon = new ImageIcon(powersmallImage);
ImageIcon rmallIcon = new ImageIcon(readictionsmallImage);
JButton squarebuttion = new JButton(smallIcon);
JButton cubebuttion = new JButton(cmallIcon);
JButton powerbuttion = new JButton(pmallIcon);
JButton readictionbuttion = new JButton(rmallIcon);
public Calcuator() {
super("计算器");
this.setBounds(400, 250, 900, 680);
// 设置窗体图片
// this.setIconImage(walkpaperimage);
this.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
// 设置窗体的布局形式
GridBagLayout gr = new GridBagLayout();
GridBagConstraints gc = new GridBagConstraints();
// 设置窗体布局
this.setLayout(gr);
// 创建模板
JPanel jp1 = createPanel1();
JPanel jp2 = createPanel2();
// 对整个窗体进行网格包布局 jp1,jp4
gc.weightx = 90;
gc.weighty = 68;
gc.fill = GridBagConstraints.BOTH;
gc.gridwidth = 7;
gc.gridheight = 10;
gc.gridx = 0;
gc.gridy = 0;
gr.setConstraints(jp1, gc);
this.add(jp1);
gc.gridwidth = 3;
gc.gridheight = 10;
gc.gridx = 7;
gc.gridy = 0;
gr.setConstraints(jp2, gc);
this.add(jp2);
this.setVisible(true);
}
private JPanel createPanel1() {
// 总的面板
JPanel panel = new JPanel();
JPanel keyPanel = new JPanel();
//设置每个面板的布局
panel.setLayout(new BorderLayout());
keyPanel.setLayout(new GridLayout(6, 7, 2, 2));
//实例化按钮监听对象
ButtonAction ba = new ButtonAction();
JButton[][] button = new JButton[][] { { new JButton("("), new JButton(")"), new JButton("1/X"),
new JButton("mc"), new JButton("m+"), new JButton("m-"), new JButton("mr"),
},
{ squarebuttion, cubebuttion, powerbuttion, new JButton("C"), new JButton("/"), new JButton("*"),
new JButton("ms"), },
{ new JButton("X!"), new JButton("√"), readictionbuttion, new JButton("7"), new JButton("8"),
new JButton("9"), new JButton("←"), },
{ new JButton("e"), new JButton("ln"), new JButton("log"), new JButton("4"), new JButton("5"),
new JButton("6"), new JButton("-"), },
{ new JButton("sin"), new JButton("cos"), new JButton("tan"), new JButton("1"), new JButton("2"),
new JButton("3"), new JButton("+"), },
{ new JButton("Deg"), new JButton("|x|"), new JButton("π"), new JButton("%"), new JButton("0"),
new JButton("."), new JButton("="), } };
// 设置文本框的字体
Font font = new Font("仿宋", Font.ROMAN_BASELINE, 56);
text.setFont(font);
text.setEditable(false);
panel.setLayout(new BorderLayout());
Font keyfont = new Font("Dialog", Font.BOLD, 14);
for (int i = 0; i < 6; i++)
for (int j = 0; j < 7; j++) {
if (j < 3)
button[i][j].setFont(keyfont);
// //*新增,设置按键为透明
// button[i][j].setOpaque(false);
//
keyPanel.add(button[i][j]);
}
panel.add("North", text);
panel.add("Center", keyPanel);
//
for (int i = 0; i < 6; i++)
for (int j = 0; j < 7; j++) {
button[i][j].addActionListener(ba);
}
button[5][0].addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String input = e.getActionCommand();
if (input.equals("Deg")) {
button[5][0].setText("Rad");
TrigCalculMethod = 1;
} else if (input.equals("Rad")) {
button[5][0].setText("Deg");
TrigCalculMethod = 0;
}
}
});
return panel;
}
private JPanel createPanel2() {
JPanel panel1 = new JPanel();
//按钮面板
JPanel panel2 = new JPanel();
CardPanel.setBackground(Color.pink);
panel1.setLayout(new BorderLayout());
panel2.add(record);
panel2.add(mermory);
panel1.add("North", panel2);
panel1.add("Center", CardPanel);
//设置历史记录框和保存框的字体
Font font1 = new Font("Verdana", Font.ROMAN_BASELINE, 12);
recordArea.setFont(font1);
mermoryArea.setFont(font1);
recordArea.setEditable(false);
mermoryArea.setEditable(false);
CardPanel.setLayout(cards);
recordArea.setBackground(Color.gray);
mermoryArea.setBackground(Color.gray);
CardPanel.add(recordArea, "card1");
CardPanel.add(mermoryArea, "card2");
record.addActionListener((ActionListener) this);
mermory.addActionListener((ActionListener) this);
return panel1;
}
public void actionPerformed(ActionEvent e) {
// 如果用户单击nextbutton,执行的语句
// Object record;
// ResultSet card;
if (e.getSource() == record) {
// 切换cardPanel面板中当前组件之后的一个组件
// 若当前组件为最后添加的组件,则显示第一个组件,即卡片组件显示是循环的。
cards.first(CardPanel);
}
if (e.getSource() == mermory) {
// 切换cardPanel面板中当前组件之前的一个组件
// 若当前组件为第一个添加的组件,则显示最后一个组件,即卡片组件显示是循环的。
cards.last(CardPanel);
}
}
private class ButtonAction implements ActionListener {
@Override
public void actionPerformed(ActionEvent e) {
String input = e.getActionCommand();
// JButton temp=e.getSource();
// 常量运算符号
if (input.equals("0") || input.equals("1") || input.equals("2") || input.equals("3") || input.equals("4")
|| input.equals("5") || input.equals("6") || input.equals("7") || input.equals("8")
|| input.equals("9") || input.equals(".") || input.equals("(") || input.equals(")")
|| input.equals("e") || input.equals("π") || input.equals("%")) {
if (equal_flag == 1) {
if (input.equals(".")) {
mathNow = "0" + input;
showNow = "0" + input;
temp = "0.";
} else {
if (!input.equals("%")) {
mathNow = input;
showNow = input;
temp = input;
}
if (input.equals("%")) {
// mathNow=result+"%";
mathNow = result + "*0.01";
showNow = result + "%";
temp = input;
// mathPast = "";
// result = "";
//// text.setText(showNow);
// equal_flag = 0;
}
}
mathPast = "";
result = "";
text.setText(showNow);
equal_flag = 0;
} else {
if (input.equals(".")) {
if (mathNow.length() == 0) { // 1.mathNow为空,+0.
mathNow += "0.";
showNow += "0.";
} else if (isChar(mathNow.charAt(mathNow.length() - 1))) { // 2.mathNow的最后一个字符为oper,+0.
mathNow += "0.";
showNow += "0.";
} else if (isNum(mathNow.charAt(mathNow.length() - 1)) && (!hasPoint(temp))) { // 3.mathNow的最后一个字符为num,+.
mathNow += ".";
showNow += ".";
} else { // 4.除此之外,不加
mathNow += "";
showNow += "";
}
temp += input;
} else {
if (!input.equals("e") && !input.equals("π") && !input.equals("(") && !input.equals(")")) {
temp += input;
// System.out.println(" "+temp);
}
// 往mathNow里面添加输入的字符
if (input.equals("%")) {
if (mathNow.equals("")) {
mathNow = "";
showNow = "";
}
if (!isChar(mathNow.charAt(mathNow.length() - 1))) {
mathNow += "*0.01";
showNow += "%";
}
} else {
mathNow += input;
showNow += input;
}
// System.out.println(mathNow+"test"+temp);
}
// 向text里添加内容
if (input.equals(".") && hasPoint(temp))
text.setText(showNow);
else
//// {
// if (!temp.contains("%")&&input.equals("%")){
//// if (temp.contains("%"))
// text.append(input);
// System.out.println("temp"+temp);
// }
// else
// if (!input.equals("%"))
text.append(input);
// }
}
}
// 运算符号
if (input.equals("+") || input.equals("-") || input.equals("*") || input.equals("/")) {
temp = "";
// 刚刚进行过一次运算
if (equal_flag == 1) {
mathNow = result + input;
showNow = result + input;
mathPast = "";
result = "";
text.setText(showNow);
equal_flag = 0;
} else {
if (mathNow.equals("") && input.equals("-")) {
mathNow += input;
showNow += input;
}
else if (!mathNow.equals("")) {
if (mathNow.charAt(mathNow.length() - 1) == '(' && input.equals("-")) {
showNow += input;
mathNow += input;
text.append(input);
}
if (isNum(mathNow.charAt(mathNow.length() - 1)) || mathNow.charAt(mathNow.length() - 1) == '!'
|| mathNow.charAt(mathNow.length() - 1) == ')'
|| mathNow.charAt(mathNow.length() - 1) == 'π'
|| mathNow.charAt(mathNow.length() - 1) == 'e'
|| mathNow.charAt(mathNow.length() - 1) == '%')
mathNow += input;
showNow += input;
}
if (result.equals("")) {
if (mathNow.equals("-") && input.equals("-"))
// text.append("-");
text.setText("-");
else {
// if (mathNow.charAt(mathNow.length()-1)=='('&&input.equals("-")){
// text.append(input);
// System.out.println(input+"test.1");
// }
if (!isChar(text.getText().charAt(text.getText().length() - 1))
&& text.getText().charAt(text.getText().length() - 1) != '(')
text.append(input);
}
}
// if(!result.equals("")) {
//
// mathNow = result + input;
// text.setText(mathNow);
// result = "";
//
// }
}
}
// 函数符号
if (input.equals("1/X") || e.getSource() == squarebuttion || e.getSource() == cubebuttion
|| e.getSource() == powerbuttion || input.equals("X!") || input.equals("√")
|| e.getSource() == readictionbuttion || input.equals("ln") || input.equals("log")
|| input.equals("sin") || input.equals("cos") || input.equals("tan") || input.equals("|x|")) {
temp = "";
if (equal_flag == 1) {
if (input.equals("|x|")) {
mathNow = "abs(";
showNow = "abs(";
} else if (input.equals("1/X") || input.equals("√") || input.equals("X!")
|| e.getSource() == squarebuttion || e.getSource() == cubebuttion
|| e.getSource() == powerbuttion || e.getSource() == readictionbuttion) {
mathNow = "";
showNow = "";
} else {
mathNow = input + "(";
showNow = input + "(";
mathPast = "";
}
result = "";
text.setText(showNow);
equal_flag = 0;
// }
} else {
// if (mathNow.charAt(mathNow.length() - 1) != '+' || mathNow.charAt(mathNow.length() - 1) != '-' || mathNow.charAt(mathNow.length() - 1) != '*' || mathNow.charAt(mathNow.length() - 1) != '/') {
if (input.equals("1/X") && (isNum(mathNow.charAt(mathNow.length() - 1))
|| mathNow.charAt(mathNow.length() - 1) == ')')) {
mathNow += "^(-1)";
showNow += "^(-1)";
text.append("^(-1)");
} else if (e.getSource() == squarebuttion && (isNum(mathNow.charAt(mathNow.length() - 1))
|| mathNow.charAt(mathNow.length() - 1) == ')')) {
mathNow += "^(2)";
showNow += "^(2)";
text.append("^(2)");
} else if (e.getSource() == cubebuttion && (isNum(mathNow.charAt(mathNow.length() - 1))
|| mathNow.charAt(mathNow.length() - 1) == ')')) {
mathNow += "^(3)";
showNow += "^(3)";
text.append("^(3)");
} else if (e.getSource() == powerbuttion && (isNum(mathNow.charAt(mathNow.length() - 1))
|| mathNow.charAt(mathNow.length() - 1) == ')')) {
mathNow += "^(";
showNow += "^(";
text.append("^(");
} else if (input.equals("X!") && (isNum(mathNow.charAt(mathNow.length() - 1))
|| mathNow.charAt(mathNow.length() - 1) == ')')) {
mathNow += "!";
showNow += "!";
text.append("!");
} else if (input.equals("√") && (isNum(mathNow.charAt(mathNow.length() - 1))
|| mathNow.charAt(mathNow.length() - 1) == ')')) {
mathNow += "^(1/2)";
showNow += "^(1/2";
text.append("^(1/2)");
} else if (e.getSource() == readictionbuttion && (isNum(mathNow.charAt(mathNow.length() - 1))
|| mathNow.charAt(mathNow.length() - 1) == ')')) {
mathNow += "^(1/";
showNow += "^(1/";
text.append("^(1/");
} else if (input.equals("ln")) {
mathNow += "ln(";
showNow += "ln(";
text.append("ln(");
} else if (input.equals("log")) {
mathNow += "log(";
showNow += "log(";
text.append("log(");
} else if (input.equals("sin")) {
mathNow += "sin(";
showNow += "sin(";
text.append("sin(");
} else if (input.equals("cos")) {
mathNow += "cos(";
showNow += "cos(";
text.append("cos(");
} else if (input.equals("tan")) {
mathNow += "tan(";
showNow += "tan(";
text.append("tan(");
} else if (input.equals("|x|")) {
mathNow += "abs(";
showNow += "abs(";
text.append("abs(");
}
}
}
// 功能键
if (input.equals("mc") || input.equals("m+") || input.equals("m-") || input.equals("mr")
|| input.equals("ms") || input.equals("←") || input.equals("=") || input.equals("deg")
|| input.equals("C")) {
if (input.equals("C"))
fc();
else if (input.equals("ms"))
fms();
else if (input.equals("mr"))
fmr();
else if (input.equals("m+"))
fmadd();
else if (input.equals("mc"))
fmc();
else if (input.equals("m-"))
fmdecreae();
else if (input.equals("←"))
fbtn_del();
else if (input.equals("="))
feual();
}
}
}
//出错时调用该函数
private void ferror() {
if (mathNow.length() < text.getColumns()) {
text.append("\n");
for (int i = 0; i < text.getColumns() - 5; i++)
text.append(" ");
text.append("error");
} else if (mathNow.length() > text.getColumns()) {
text.append("\n");
for (int i = 0; i < mathNow.length() - 4; i++)
text.append(" ");
text.append("error");
}
}
//点击m相应键时调用这些函数
private void fms() {
// 通过计算将结果保存在m中
m = result;
mermoryArea.append("m=" + m + "\n");
}
private void fmr() {
mathNow = m;
text.setText(mathNow);
}
private void fmadd() {
// 计算出来的结果加上M的值
m = String.valueOf(Double.parseDouble(m) + Double.parseDouble(result));
mermoryArea.append("m=" + m + "\n");
}
private void fmdecreae() {
// m减去计算出的值
m = String.valueOf(Double.parseDouble(m) - Double.parseDouble(result));
mermoryArea.append("m=" + m);
}
private void fmc() {
m = "";
mermoryArea.setText("已刷新1\n");
}
private void fc() {
equal_flag = 0;
mathNow = "";
mathPast = "";
showNow = "";
text.setText("");
result = "";
recordArea.setText(ReSetrecordArea);
mermoryArea.setText("内存");
}
private void fbtn_del() {
if (mathNow.length() != 0) {
mathNow = mathNow.substring(0, mathNow.length() - 1);
showNow = showNow.substring(0, showNow.length() - 1);
text.setText(showNow);
}
}
private void feual() {
if (equal_flag == 1) {
text.append("");
} else {
mathNow = fparentthesis(mathNow);
showNow = fparentthesis(showNow);
mathNow = fDeltePare(mathNow);
showNow = fDeltePare(showNow);
// System.out.println(mathNow+"fDetelttest");
mathPast = mathNow;
mathNow = "";
ScienCalcuator sr = new ScienCalcuator();
sr.angle_metric = TrigCalculMethod;
result = sr.fScienceCalcuator(mathPast);
;
if (!result.equals("null"))
fVisResuable(showNow);
recordArea.append("\n" + showNow + "=" + result);
equal_flag = 1;
}
}
private boolean isChar(char con_char) {
return con_char == '+' || con_char == '-' || con_char == '*' || con_char == '/' || con_char == '×'
|| con_char == '÷';
}
//显示结果函数
void fVisResuable(String con_str) {
if (con_str.length() < 18) {
text.append("\n");
text.append("=" + result);
} else {
text.append("\n");
for (int i = 0; i < con_str.length() - result.length(); i++)
text.append(" ");
text.append("=" + result);
System.out.println(text.getColumns() + "\n" + con_str.length());
}
}
private boolean isNum(char con_char) {
return con_char == '0' || con_char == '1' || con_char == '2' || con_char == '3' || con_char == '4'
|| con_char == '5' || con_char == '6' || con_char == '7' || con_char == '8' || con_char == '9';
}
//与零进行比较,目的时限制小数再加小数点的情况
private boolean hasPoint(String con_str) {
return con_str.indexOf('.') >= 0;
}
// 删除多余的括号
private String fDeltePare(String con_str) {
for (int i = 0; i < con_str.length(); i++) {
int Index = -1;
String mind_str;
String temp_str;
if (con_str.charAt(i) == '(') {
Index = i;
if (Index == 0) {
int j = Index + 1;
int LeftBrackSum = 1;
int RightBrackSum = 0;
while (LeftBrackSum != RightBrackSum) {
if (con_str.charAt(j) == '(')
LeftBrackSum += 1;
if (con_str.charAt(j) == ')')
RightBrackSum += 1;
j++;
}
mind_str = con_str.substring(Index + 1, j - 1);
temp_str = "(" + mind_str + ")";
if (mind_str.contains("("))
mind_str = fDeltePare(mind_str);
// else
if (!mind_str.contains("(") && !mind_str.contains("+") && !mind_str.contains("-")
&& !mind_str.contains("*") && !mind_str.contains("/") && !mind_str.contains("%")) {
con_str = con_str.replace(temp_str, mind_str);
}
} else if (Index != 0 && isChar(con_str.charAt(Index - 1))) {
int j = Index + 1;
int LeftBrackSum = 1;
int RightBrackSum = 0;
while (LeftBrackSum != RightBrackSum) {
if (con_str.charAt(j) == '(')
LeftBrackSum += 1;
if (con_str.charAt(j) == ')')
RightBrackSum += 1;
j++;
}
mind_str = con_str.substring(Index + 1, j - 1);
temp_str = "(" + mind_str + ")";
if (mind_str.contains("(")) {
mind_str = fDeltePare(mind_str);
}
if (!mind_str.contains("(") && !mind_str.contains("+") && !mind_str.contains("-")
&& !mind_str.contains("*") && !mind_str.contains("/") && !mind_str.contains("%")) {
con_str = con_str.replace(temp_str, mind_str);
}
}
}
}
return con_str;
}
private String fparentthesis(String con_mathnow) {
// 补全括号
int leftNum = 0;
int rightNum = 0;
for (int i = 0; i < con_mathnow.length(); i++) {
if (con_mathnow.charAt(i) == '(')
leftNum++;
if (con_mathnow.charAt(i) == ')')
rightNum++;
}
int missingNum = leftNum - rightNum; // 缺失的 ) 数量
while (missingNum > 0) {
con_mathnow += ')';
missingNum--;
}
return con_mathnow;
}
public static void main(String[] args) {
Calcuator f = new Calcuator();
}
}
3. ScienCalcuator
类
- 功能概述
- 该类提供了科学计算功能,包括三角函数计算、幂运算、对数运算、阶乘运算等,基于
BaseCalcuator
类进行扩展。
- 该类提供了科学计算功能,包括三角函数计算、幂运算、对数运算、阶乘运算等,基于
- 关键成员变量
angle_metric
:用于指定三角函数计算的角度制或弧度制。
- 关键方法
fPower
:处理幂运算,包括解析底数和指数并进行计算。fTraingle
:处理三角函数运算,根据设置的角度制或弧度制计算结果。fBrackAddZero
:在括号内数字为负时添加前导0。fBaseCalcuator
:调用BaseCalcuator
类进行基本运算。fScienceCalcuator
:综合处理科学计算表达式,包括替换特殊字符(如π
和e
),按顺序调用其他方法处理各种运算。isOper
和isNum
:辅助方法,用于判断字符是否为运算符或数字。fpreactorial
和factorial
:处理阶乘运算。
public class ScienCalcuator {
public int angle_metric = 0;// 三角函数计算的方式,0为角度值,1为弧度值
String fPower(String con_str) {
while (con_str.contains("^")) {
// 1.中间寻找的点
int midIndex = con_str.lastIndexOf("^");
// 2.获取左边参数
double leftNum; // 左边的数
String leftStr; // 左边math字符串
int leftIndex = midIndex - 1;
if (con_str.charAt(leftIndex) == ')') { // 1.左边是一个表达式,即左边用括号括起来
int i = leftIndex - 1;
int LeftBrackSum = 0;
int RightBrackSum = 1;
while (LeftBrackSum != RightBrackSum) {
if (con_str.charAt(i) == '(')
LeftBrackSum += 1;
if (con_str.charAt(i) == ')')
RightBrackSum += 1;
i--;
}
String subLeftMath = con_str.substring(i + 2, leftIndex);
if (subLeftMath.contains("sin") || subLeftMath.contains("^") || subLeftMath.contains("cos")
|| subLeftMath.contains("tan") || subLeftMath.contains("ln") || subLeftMath.contains("log")
|| subLeftMath.contains("!") || subLeftMath.contains("abs")) {
String subLeftMath1 = subLeftMath;
leftNum = Double.parseDouble(fScienceCalcuator(subLeftMath1));
} else
leftNum = Double.parseDouble(fBaseCalcuator(subLeftMath));
if (leftNum == Double.MAX_VALUE) // 每次计算要判断是否出现 math error
return String.valueOf(Double.MAX_VALUE);
leftStr = "(" + subLeftMath + ")";
} else { // 2.左边是一个数
// 注意:判定index范围一定要在左边,否则可能出现IndexOutOfRange异常
while (leftIndex >= 0 && !isOper(con_str.charAt(leftIndex))) {
leftIndex--;
}
leftStr = con_str.substring(leftIndex + 1, midIndex);
leftNum = Double.parseDouble(leftStr);
}
// 3.获取右边参数
double rightNum;
String rightStr;
int rightIndex = midIndex + 1;
if (con_str.charAt(rightIndex) == '(') {
int i = rightIndex + 1;
int LeftBrackSum = 1;
int RightBrackSum = 0;
while (LeftBrackSum != RightBrackSum) {
if (con_str.charAt(i) == '(')
LeftBrackSum += 1;
if (con_str.charAt(i) == ')')
RightBrackSum += 1;
i++;
}
String subRightMath = con_str.substring(rightIndex + 1, i - 1);
if (subRightMath.contains("sin") || subRightMath.contains("cos") || subRightMath.contains("^")
|| subRightMath.contains("tan") || subRightMath.contains("ln") || subRightMath.contains("log")
|| subRightMath.contains("!") || subRightMath.contains("abs")) {
String subRightMath1 = subRightMath;
rightNum = Double.parseDouble(fScienceCalcuator(subRightMath1));
} else
rightNum = Double.parseDouble(fBaseCalcuator(subRightMath));
if (rightNum == Double.MAX_VALUE)
return String.valueOf(Double.MAX_VALUE);
rightStr = "(" + subRightMath + ")";
} else {
while (rightIndex < con_str.length() && !isOper(con_str.charAt(rightIndex))) {
rightIndex++;
}
rightStr = con_str.substring(midIndex + 1, rightIndex);
rightNum = Double.parseDouble(rightStr);
}
// 4.得到完整的运算式并运算和替换
String wholeMath = leftStr + "^" + rightStr;
double result = Math.pow(leftNum, rightNum);
con_str = con_str.replace(wholeMath, String.valueOf(result));
}
return con_str;
}
String fTraingle(String con_str) {
while (con_str.contains("sin") || con_str.contains("cos") || con_str.contains("tan") || con_str.contains("ln")
|| con_str.contains("log") || con_str.contains("abs")) {
String tempor = null;// 用于暂时保留三角运算符
int beginIndex = 0;// 保留运算符号后面括号的索引值
String temp = "";
if (con_str.contains("sin") || con_str.contains("cos") || con_str.contains("tan") || con_str.contains("ln")
|| con_str.contains("log") || con_str.contains("abs")) {
if (con_str.contains("sin")) {
tempor = "sin";
beginIndex = con_str.lastIndexOf(tempor) + 3;
} else if (con_str.contains("cos")) {
tempor = "cos";
beginIndex = con_str.lastIndexOf(tempor) + 3;
} else if (con_str.contains("tan")) {
tempor = "tan";
beginIndex = con_str.lastIndexOf(tempor) + 3;
} else if (con_str.contains("ln")) {
tempor = "ln";
beginIndex = con_str.lastIndexOf(tempor) + 2;
if (beginIndex - 2 > 0) {
if (isNum(con_str.charAt(beginIndex - 3)) || con_str.charAt(beginIndex - 3) == '.') {
int i = con_str.lastIndexOf(tempor) - 1;
while ((isNum(con_str.charAt(i)) || con_str.charAt(i) == '.') && i != 0) {
i--;
}
// 进行字符串的赋值
if (i > 0)
temp = con_str.substring(i + 1, con_str.lastIndexOf(tempor));
else
temp = con_str.substring(i, con_str.lastIndexOf(tempor));
}
if (con_str.charAt(beginIndex - 3) == ')') {
int leftIndex = beginIndex - 3;
int i = leftIndex - 1;
int LeftBrackSum = 0;
int RightBrackSum = 1;
while (LeftBrackSum != RightBrackSum) {
if (con_str.charAt(i) == '(')
LeftBrackSum += 1;
if (con_str.charAt(i) == ')')
RightBrackSum += 1;
i--;
}
temp = con_str.substring(i + 1, leftIndex + 1);
System.out.println(temp + "templn");
}
//// else
// if (con_str.charAt(beginIndex-3)=='e'||con_str.charAt(beginIndex-3)=='π') {
// temp = "";
// System.out.println("提前知道数");
// }
}
} else if (con_str.contains("abs")) {
tempor = "abs";
beginIndex = con_str.lastIndexOf(tempor) + 3;
} else if (con_str.contains("log")) {
tempor = "log";
beginIndex = con_str.lastIndexOf(tempor) + 3;
if (beginIndex - 3 > 0) {
if (isNum(con_str.charAt(beginIndex - 4)) || con_str.charAt(beginIndex - 4) == '.') {
int i = con_str.lastIndexOf(tempor) - 1;
while ((isNum(con_str.charAt(i)) || con_str.charAt(i) == '.') && i != 0) {
i--;
}
// 进行字符串的赋值
if (i > 0)
temp = con_str.substring(i + 1, con_str.lastIndexOf(tempor));
else
temp = con_str.substring(i, con_str.lastIndexOf(tempor));
}
if (con_str.charAt(beginIndex - 4) == ')') {
int leftIndex = beginIndex - 4;
int i = leftIndex - 1;
int LeftBrackSum = 0;
int RightBrackSum = 1;
while (LeftBrackSum != RightBrackSum) {
if (con_str.charAt(i) == '(')
LeftBrackSum += 1;
if (con_str.charAt(i) == ')')
RightBrackSum += 1;
i--;
}
temp = con_str.substring(i + 1, leftIndex + 1);
// System.out.println(temp+"templn");
}
}
}
}
// 1.获取()内运算式并计算出结果,此时假设()不再包含复杂的科学运算
if (con_str.charAt(beginIndex) == '(') {
int i = beginIndex + 1;
int LeftBrackSum = 1;
int RightBrackSum = 0;
while (LeftBrackSum != RightBrackSum) {
if (con_str.charAt(i) == '(')
LeftBrackSum += 1;
if (con_str.charAt(i) == ')')
RightBrackSum += 1;
i++;
}
// 获取括号内得字符串
String subMath = con_str.substring(beginIndex + 1, i - 1);
double subResult;
if (subMath.contains("sin") || subMath.contains("cos") || subMath.contains("^")
|| subMath.contains("tan") || subMath.contains("ln") || subMath.contains("log")
|| subMath.contains("!") || subMath.contains("abs")) {
String subRightMath1 = subMath;
subResult = Double.parseDouble(fScienceCalcuator(subRightMath1));
} else
subResult = Double.parseDouble(fBaseCalcuator(subMath));
if (subResult == Double.MAX_VALUE) // 每次计算要判断是否出现 math error
return String.valueOf(Double.MAX_VALUE);
// 3.匹配scienceOper进行科学运算,并替换相应部分
String tempMath;
double tempResult = 0;
int DEG = 0; // 判断角度制
switch (tempor) {
case "sin":
tempMath = "sin(" + subMath + ")";
if (angle_metric == DEG) {
tempResult = Math.sin(subResult / 180 * Math.PI); // 将默认的 Rad → Deg
} else {
tempResult = Math.sin(subResult);
}
con_str = con_str.replace(tempMath, String.valueOf(tempResult));
break;
case "cos":
tempMath = "cos(" + subMath + ")";
if (angle_metric == DEG) {
tempResult = Math.cos(subResult / 180 * Math.PI);
} else {
tempResult = Math.cos(subResult);
}
con_str = con_str.replace(tempMath, String.valueOf(tempResult));
break;
case "tan":
tempMath = "tan(" + subMath + ")";
if (angle_metric == DEG) {
if (subResult == 90)
con_str = "error";
else
tempResult = Math.tan(subResult / 180 * Math.PI);
} else {
if (subResult == Math.PI / 2)
con_str = "error";
else
tempResult = Math.tan(subResult);
}
con_str = con_str.replace(tempMath, String.valueOf(tempResult));
break;
case "ln":
tempMath = temp + "ln(" + subMath + ")";
if (!temp.equals("")) {
temp = fScienceCalcuator(temp);
subResult = Math.pow(subResult, Double.parseDouble(temp));
// System.out.println("temp="+temp);
}
tempResult = Math.log(subResult);
con_str = con_str.replace(tempMath, String.valueOf(tempResult));
break;
case "log":
tempMath = temp + "log(" + subMath + ")";
if (!temp.equals("")) {
temp = fScienceCalcuator(temp);
subResult = Math.pow(subResult, Double.parseDouble(temp));
// System.out.println("temp="+temp);
}
tempResult = Math.log10(subResult);
con_str = con_str.replace(tempMath, String.valueOf(tempResult));
break;
case "abs":
tempMath = "abs(" + subMath + ")";
tempResult = Math.abs(subResult);
con_str = con_str.replace(tempMath, String.valueOf(tempResult));
break;
default:
break;
}
}
//
//
}
return con_str;
}
private String fBrackAddZero(String con_str) {
for (int i = 0; i < con_str.length(); i++) {
String mind_str;
String temp_str;
if (con_str.charAt(i) == '(') {
int Index = i;
int j = Index + 1;
if (con_str.charAt(j) == '-') {
int LeftBrackSum = 1;
int RightBrackSum = 0;
while (LeftBrackSum != RightBrackSum) {
if (con_str.charAt(j) == '(')
LeftBrackSum += 1;
if (con_str.charAt(j) == ')')
RightBrackSum += 1;
j++;
}
mind_str = con_str.substring(Index + 1, j - 1);
con_str = con_str.replace(mind_str, "0" + mind_str);
}
}
}
return con_str;
}
private String fBaseCalcuator(String con_str) {
BaseCalcuator sc = new BaseCalcuator();
con_str = fBrackAddZero(con_str);
sc.math = con_str;
sc.fCalcuate();
String result = sc.restult;
sc.data.clear();
sc.stack.clear();
return result;
}
public String fScienceCalcuator(String con_str) {
con_str = con_str.replace(" ", ""); // 去掉math中的所有空格
con_str = con_str.replaceAll("π", String.valueOf(Math.PI)); // 替换π
con_str = con_str.replaceAll("e", String.valueOf(Math.exp(1))); // 替换自然指数e
while (con_str.contains("^") || con_str.contains("sin") || con_str.contains("!") || con_str.contains("cos")
|| con_str.contains("tan") || con_str.contains("ln") || con_str.contains("log")
|| con_str.contains("abs")) {
if (con_str.contains("!"))
con_str = fpreactorial(con_str);
con_str = fTraingle(con_str);
con_str = fPower(con_str);
}
return fBaseCalcuator(con_str);
}
private boolean isOper(char con_char) {
return con_char == '+' || con_char == '-' || con_char == '*' || con_char == '/';
}
private boolean isNum(char con_char) {
return con_char == '0' || con_char == '1' || con_char == '2' || con_char == '3' || con_char == '4'
|| con_char == '5' || con_char == '6' || con_char == '7' || con_char == '8' || con_char == '9';
}
private String fpreactorial(String con_str) {
while (con_str.contains("!")) {
// System.out.println(con_str);
int Index = con_str.lastIndexOf("!");
int RightIndex = Index - 1;
String PreactorialResult;
String left_str;
if (con_str.charAt(RightIndex) == ')') {
// 左边是式子
int i = RightIndex - 1;
int LeftBrackSum = 0;
int RightBrackSum = 1;
String LeftSum;
while (LeftBrackSum != RightBrackSum) {
if (con_str.charAt(i) == '(')
LeftBrackSum += 1;
if (con_str.charAt(i) == ')')
RightBrackSum += 1;
i--;
}
String subLeftMath = con_str.substring(i + 2, RightIndex);
System.out.println(subLeftMath + "开头处理");
left_str = "(" + subLeftMath + ")" + "!";
if (con_str.contains("^") || con_str.contains("sin") || con_str.contains("cos")
|| con_str.contains("tan") || con_str.contains("!") || con_str.contains("ln")
|| con_str.contains("log"))
LeftSum = fScienceCalcuator(subLeftMath);
else
LeftSum = fBaseCalcuator(subLeftMath);
if (LeftSum == String.valueOf(Double.MAX_VALUE))
return String.valueOf(Double.MAX_VALUE);
PreactorialResult = factorial(LeftSum);
con_str = con_str.replace(left_str, PreactorialResult);
} else if (isNum(con_str.charAt(RightIndex))) {// 左边是一个数
System.out.println(con_str + " " + RightIndex);
int i = RightIndex;
String leftMath = null;
while (i >= 0 && !isOper(con_str.charAt(i))) {
i--;
}
leftMath = con_str.substring(i + 1, Index);
System.out.println(leftMath + "阶乘开头处理");
left_str = leftMath + "!";
PreactorialResult = factorial(leftMath);
con_str = con_str.replace(left_str, PreactorialResult);
}
}
return con_str;
}
private String factorial(String con_str) {
// if(con_str.contains("^")||con_str.contai))
if (con_str.contains("^") || con_str.contains("sin") || con_str.contains("cos") || con_str.contains("tan")
|| con_str.contains("ln") || con_str.contains("log") || con_str.contains("abs"))
con_str = fScienceCalcuator(con_str);
else
con_str = fBaseCalcuator(con_str);
if (Double.parseDouble(con_str) % 1 != 0)
return "error";
else {
if (con_str.equals("0"))
return "1";
else {
double sum = 1;
for (int i = 1; i <= Double.parseDouble(con_str); i++)
sum = sum * i;
return String.valueOf(sum);
// return con_str;
}
}
}
}