公告
日历
| 日 | 一 | 二 | 三 | 四 | 五 | 六 |
---|
29 | 30 | 31 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 | 10 | 11 | 12 | 13 | 14 | 15 | 16 | 17 | 18 | 19 | 20 | 21 | 22 | 23 | 24 | 25 | 26 | 27 | 28 | 29 | 30 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9 |
|
统计
- 随笔 - 36
- 文章 - 10
- 评论 - 94
- 引用 - 0
导航
常用链接
留言簿(5)
随笔分类(49)
随笔档案(36)
文章分类(11)
文章档案(10)
相册
dyerac
搜索
积分与排名
最新随笔
最新评论

阅读排行榜
评论排行榜
|
有感于windows自带计算器的不好使,最近心血来潮按自己需求开发了一个多功能计算器。其核心的一部分来自于网上的学习资料,因此我也不敢私藏代码,特拿出来和大家分享心得。 计算器功能如下: 1.支持运行时更换界面皮肤,水印和按钮形状等外观显示。 2.支持sin, cos, tan, cot, arcsin, arccos, arctan, arccot, !, log, ln, +, -, *, /, %, 乘方等基本运算,支持连续运算并自带PI,E的精确值。 3.支持表达式计算,支持设置变量,可以轻松的实现公式运算。 4.无限的结果保存,完全对用户透明,用户可以轻松的存储和读取先前的操作结果. 5.能够分析用户操作尤其是表达式中的语法错误,提醒用户而不是返回错误结果。


设计思路:
整个程序的
GUI
由两部分组成。结果存储由
JDialog
完成,
JDialog
内含一个
JList
存放结果。主界面由
JMenuBar
和
JTabbedPane
组成,
JTabbedPane
的两个子界面分别用作按键式计算器和表达式式计算器。
关于界面的构建工作全部由
CalculatorFace
类完成,同时按键式计算器的后台计算工作也有该类完成。
Parser
类则负责解析表达式返回计算结果。
CalculatorFace
调用
Parser
进行表达式计算工作。
在处理按键式计算时,各种计算操作符号显然可以分为两类:单操作数和双操作数。单操作数计算只需要取出显示框中内容,进行计算再将结果显示即可。双操作数计算则显得比较麻烦。因为需要实现连续计算,所以必须保存上次的操作符号和上次输入的结果。为此增加lastOperator字段和number1,number2字段分别存储前次操作符和对应的操作数。 运行机制如下: 当按下新键时,将number2->number1,显示框中内容取出作为number2,同时根据lastOperator中内容进行计算(number1 lastOperator number2),计算完成后,将这次按键内容保存到lastOperator中。要注意的是,当“=”按下时,将取消连续运算。因此添加boolean字段continued用来判断是否进行连续运算。 考虑到用户的误操作,即可能不小心按错了按钮,因此每次运算应以输入新数字前最后一个操作符号为准。因此,continued事实上也控制运算是否进行,每次双操作运算后,continued赋值为false,输入数字后才重新为真。当continued为false时,程序只是简单的把按键值赋予lastOperator而不进行运算工作。 而对于数字按键,唯一需要注意的是按下操作键后,再输入数据需要将显示框清空后从头输入;否则新数字将在显示框原有内容尾部添加。completed字段用于控制该情形。上述例外在于,第一次使用计算器时,即使没有按下操作键,也应该重新显示数字。First字段将处理这一情形。
表达式解析则通过Parser类完成。getToken方法负责将表达式中基本的单元取出。这些基本单元包括:变量,数字和操作符号。运行时,首先将表达式中变量替换成其值,对处理好的表达式从左至右取出单元进行计算。计算采用递归下降的流式处理,调用按计算优先级排列好的各种函数,每种函数处理同一优先级的运算。 优先级列表为: 括号,阶乘,正负号,三角函数/对数函数/反三角函数,乘方,乘/除/模运算,加减运算。 下面举例说明表达式的解析过程。表达式 10 + 5 * B 有两个项:10和5*B,第二项包括两个因数:5和B,分别是一个数字和一个变量 再看另外一个例子。表达式 14 * (7 – C) 有两个因数:14和(7-C),分别是一个数字和一个圆括号表达式。圆括号表达式包括两个项:一个数字和一个变量。 上述过程形成了递归下降解析器的基础。递归下降解析器是一组互相递归的方法,这些方法以一种链式方式实现生成规则。在每个适当的步骤上,解析器以代数学规定的正确顺序执行指定的操作。为了解释如何使用生成规则来解析表达式,采用下面的表达式来跟踪解析过程: 9/3 – (100 + 56) 整个解析过程如下: (1) 获得第一项9/3; (2) 获得第一项的两个因数并完成除法运算,得到结果3; (3) 获得第二项(100+56)。在这一步启动递归分析过程处理括号内的子表达式; (4) 获得其中的两项并完成加法运算,得到结果156; (5) 从第二项的递归计算过程中返回; (6) 3减去156,答案是-153。
Bugs: 经过同学的友情测试,现发现bug如下: (1)无法将――2形式识别为2 (2)乘方运算时,当数字和’!’中出现空格或者括号时无法处理 (3)类似sinlog10形式无法识别,只能识别sin(log10) 以上将在下一版本中修订。
Uncompleted features: (1)任意进制的计算和转换 (2)角度与弧度的转换 (3)扩大计算范围(即应该使用BigDemical而不是double) 以上同样会在下一版本中实现。
下面是程序的源代码:
package
cn.com.w4t.calculator;

import
java.awt.BorderLayout;
import
java.awt.Color;
import
java.awt.GridLayout;
import
java.awt.event.ActionEvent;
import
java.awt.event.ActionListener;
import
java.util.Vector;

import
javax.swing.JButton;
import
javax.swing.JDialog;
import
javax.swing.JFrame;
import
javax.swing.JLabel;
import
javax.swing.JList;
import
javax.swing.JMenu;
import
javax.swing.JMenuBar;
import
javax.swing.JMenuItem;
import
javax.swing.JPanel;
import
javax.swing.JScrollPane;
import
javax.swing.JTabbedPane;
import
javax.swing.JTextArea;
import
javax.swing.JTextField;
import
javax.swing.UIManager;
import
javax.swing.border.EtchedBorder;
import
javax.swing.border.LineBorder;
import
javax.swing.border.TitledBorder;

import
org.jvnet.substance.SubstanceLookAndFeel;
import
org.jvnet.substance.theme.SubstancePurpleTheme;
import
org.jvnet.substance.watermark.SubstanceBinaryWatermark;


/** */
/**
* Main Application Interface
*
*
@author
td
*
*/
@SuppressWarnings(
"
serial
"
)

public
class
CalculatorFace
extends
JFrame
implements
ActionListener
{


/** */
/**
* 按键计算的结果
*/
private
double
result1;


/** */
/**
* 表达式计算的结果
*/
private
double
result2;


/** */
/**
* 二元计算是否完成,完成后下次输入数据时将从头开始而不是在原有数据后添加
*/
private
boolean
completed
=
false
;


/** */
/**
* 是否是第一次进行操作
*/
private
boolean
first
=
true
;


/** */
/**
* 是否进行连续计算,比如"="将取消连续运算
*/
private
boolean
continued
=
false
;


/** */
/**
* 被保存的先前计算结果集
*/
private
Vector
<
String
>
resultVector
=
new
Vector
<
String
>
();


/** */
/**
* 计算表达式
*/
private
String express;


/** */
/**
* 变量值
*/
private
String variables;


/** */
/**
* 表达式解析式
*/
private
Parser parser
=
new
Parser();


/** */
/**
* 操作按键
*/
private
JButton[] operatorBtns
=
new
JButton[
20
];


/** */
/**
* 操作符号
*/
private
String[] op
=
{
"
+
"
,
"
-
"
,
"
*
"
,
"
/
"
,
"
%
"
,
"
^
"
,
"
!
"
,
"
=
"
,
"
ln
"
,
"
log
"
,
"
sin
"
,
"
cos
"
,
"
tan
"
,
"
cot
"
,
"
arcsin
"
,
"
arccos
"
,
"
arctan
"
,
"
arccot
"
,
"
PI
"
,
"
E
"
}
;


/** */
/**
* 数字按键
*/
private
JButton[] numberBtns
=
new
JButton[
12
];


/** */
/**
* 保持结果的对话框
*/
private
JDialog resultHolder;


/** */
/**
* 保持结果的列表
*/
private
JList resultList;


/** */
/**
* 一些系统功能按键,显示、隐藏结果记录对话框,存储计算结果,清屏,退格
*/
private
JButton clearBtn, saveBtn, saveBtn2, backBtn, shBtn, shBtn2,
submitBtn;


/** */
/**
* 主界面
*/
private
JTabbedPane mainTab;


/** */
/**
* 输入框
*/
private
JTextField resultField1, resultField2, inputField;


/** */
/**
* 错误标签
*/
private
JLabel errorLabel1, errorLabel2;


/** */
/**
* 监听器
*/
private
ActionListener numberListener
=
new
NumberListener(),
oneOperatorListener
=
new
OneOperatorListener(),
twoOperatorListener
=
new
TwoOperatorListener();


/** */
/**
* 菜单
*/
private
JMenu fileM, setM, helpM;


/** */
/**
* 菜单栏
*/
private
JMenuBar menu;


/** */
/**
* 变量输入框
*/
private
JTextArea variableArea;


/** */
/**
* 操作数
*/
private
String number1
=
"
0.0
"
, number2
=
"
0.0
"
;


/** */
/**
* 上一次操作符号
*/
private
String lastOperator;

//
private JMenuItem fileItem, settingsItem, helpItem;
public
CalculatorFace()
{
super
();
init();
}
/** */
/**
* 初始化属性
*
*/
private
void
initReference()
{
//
init all buttons
for
(
int
i
=
0
; i
<
10
; i
++
)
{
numberBtns[i]
=
new
JButton(Integer.toString(i));
numberBtns[i].addActionListener(numberListener);
numberBtns[i].setBorder(
null
);
}
numberBtns[
10
]
=
new
JButton(
"
.
"
);
numberBtns[
10
].addActionListener(oneOperatorListener);
numberBtns[
10
].setBorder(
null
);
numberBtns[
11
]
=
new
JButton(
"
+/-
"
);
numberBtns[
11
].setBorder(
null
);
numberBtns[
11
].addActionListener(oneOperatorListener);

for
(
int
i
=
0
; i
<
op.length; i
++
)
{
operatorBtns[i]
=
new
JButton(op[i]);
if
(i
<
6
)
operatorBtns[i].addActionListener(twoOperatorListener);
else
operatorBtns[i].addActionListener(oneOperatorListener);
operatorBtns[i].setBorder(
null
);
}
clearBtn
=
new
JButton(
"
Clear
"
);
clearBtn.addActionListener(
this
);
clearBtn.setBorder(
new
EtchedBorder(EtchedBorder.LOWERED));
saveBtn
=
new
JButton(
"
Save
"
);
saveBtn.addActionListener(
this
);
saveBtn.setBorder(
new
EtchedBorder(EtchedBorder.LOWERED));
saveBtn2
=
new
JButton(
"
Save
"
);
saveBtn2.addActionListener(
this
);
saveBtn2.setBorder(
new
EtchedBorder(EtchedBorder.LOWERED));
backBtn
=
new
JButton(
"
Back
"
);
backBtn.addActionListener(
this
);
backBtn.setBorder(
new
EtchedBorder(EtchedBorder.LOWERED));
shBtn
=
new
JButton(
"
S/H
"
);
shBtn.addActionListener(
this
);
shBtn.setBorder(
new
EtchedBorder(EtchedBorder.LOWERED));
shBtn2
=
new
JButton(
"
S/H
"
);
shBtn2.addActionListener(
this
);
shBtn2.setBorder(
new
EtchedBorder(EtchedBorder.LOWERED));
submitBtn
=
new
JButton(
"
Submit
"
);
ParserListener p
=
new
ParserListener();
submitBtn.addActionListener(p);
submitBtn.setBorder(
new
EtchedBorder(EtchedBorder.LOWERED));

//
init textfileds
resultField1
=
new
JTextField(
"
0.0
"
);
resultField1.setEditable(
false
);
resultField2
=
new
JTextField(
"
0.0
"
);
resultField2.setEditable(
false
);
inputField
=
new
JTextField();
inputField.addActionListener(p);
inputField.setToolTipText(
"
输入表达式,可以含有变量,但是变量必须在下面定义
"
);
variableArea
=
new
JTextArea();
variableArea.setToolTipText(
"
输入变量值,约定形式为a=1,b=2,请勿使用s,c,t等关键字作为变量名
"
);

//
init labels
errorLabel1
=
new
JLabel();
errorLabel1.setForeground(Color.red);
errorLabel2
=
new
JLabel();
errorLabel2.setForeground(Color.red);

mainTab
=
new
JTabbedPane();

//
init menu
menu
=
new
JMenuBar();
fileM
=
new
JMenu(
"
File
"
);
fileM.setMnemonic(
'
F
'
);
setM
=
new
JMenu(
"
Settings
"
);
setM.setMnemonic(
'
S
'
);
helpM
=
new
JMenu(
"
Help
"
);
helpM.setMnemonic(
'
H
'
);
}
/** */
/**
* 初始化菜单
*
*/
private
void
initMenu()
{
menu.add(fileM);
menu.add(setM);
menu.add(helpM);
fileM.add(
new
JMenuItem(
"
Exit
"
));
setM.add(
new
JMenuItem(
"
二进制
"
));
setM.add(
new
JMenuItem(
"
八进制
"
));
setM.add(
new
JMenuItem(
"
十进制
"
));
setM.add(
new
JMenuItem(
"
十六进制
"
));
helpM.add(
new
JMenuItem(
"
Manual
"
));
helpM.add(
new
JMenuItem(
"
About
"
));
}
/** */
/**
* 初始化主界面
*
*/
private
void
initTabbedPane()
{
JPanel p1
=
new
JPanel();
JPanel p10
=
new
JPanel();
JPanel p12
=
new
JPanel();
JPanel p11
=
new
JPanel();
JPanel pc1
=
new
JPanel();
JPanel p2
=
new
JPanel();
JPanel p20
=
new
JPanel();
JPanel p22
=
new
JPanel();
JPanel p21
=
new
JPanel();

p10.setLayout(
new
GridLayout(
2
,
1
));
p10.setBorder(
new
TitledBorder(
new
LineBorder(Color.DARK_GRAY,
1
),
"
Result:
"
));
p12.setLayout(
new
GridLayout(
6
,
8
));
p11.setLayout(
new
GridLayout(
2
,
8
));
p1.setLayout(
new
BorderLayout());
pc1.setLayout(
new
BorderLayout());
pc1.setBorder(
new
TitledBorder(
new
LineBorder(Color.DARK_GRAY,
1
),
"
Input Buttons:
"
));

p20.setLayout(
new
GridLayout(
3
,
1
));
p21.setLayout(
new
BorderLayout());
p22.setLayout(
new
GridLayout(
1
,
7
));
p2.setLayout(
new
BorderLayout());

p10.add(resultField1);
p10.add(errorLabel1);


for
(
int
i
=
0
; i
<
4
; i
++
)
{
p12.add(operatorBtns[i]);
}
for
(
int
i
=
0
; i
<
4
; i
++
)
{
p12.add(
new
JLabel());
}
for
(
int
i
=
0
; i
<
4
; i
++
)
{
for
(
int
j
=
i
*
4
; j
<
i
*
4
+
4
; j
++
)
p12.add(operatorBtns[j
+
4
]);
p12.add(
new
JLabel(
""
));
for
(
int
j
=
i
*
3
; j
<
i
*
3
+
3
; j
++
)
p12.add(numberBtns[j]);
}
for
(
int
i
=
0
; i
<
8
; i
++
)
{
p12.add(
new
JLabel());
}
p11.add(shBtn);
p11.add(saveBtn);
p11.add(backBtn);
p11.add(clearBtn);
for
(
int
i
=
0
; i
<
12
; i
++
)
p11.add(
new
JLabel());

p1.add(p10,
"
North
"
);
pc1.add(p11,
"
Center
"
);
pc1.add(p12,
"
South
"
);
p1.add(pc1,
"
Center
"
);

JLabel tip
=
new
JLabel(
"
支持:sin,cos,tan,cot,arcsin,arccos,arctan,arccot,!,log,ln
"
);
p20.add(tip);
p20.add(resultField2);
p20.add(errorLabel2);
p20.setBorder(
new
TitledBorder(
new
LineBorder(Color.DARK_GRAY,
1
),
"
Result:
"
));

JPanel p210
=
new
JPanel();
p210.setLayout(
new
BorderLayout());
p210.add(
new
JLabel(
"
输入表达式
"
),
"
North
"
);
p210.add(inputField,
"
Center
"
);
p210.add(
new
JLabel(
"
输入变量值
"
),
"
South
"
);
p21.add(p210,
"
North
"
);
p21.add(variableArea,
"
Center
"
);
p21.setBorder(
new
TitledBorder(
new
LineBorder(Color.DARK_GRAY,
1
),
"
Input Express and Variables:
"
));

p22.add(
new
JLabel());
p22.add(
new
JLabel());
p22.add(saveBtn2);
p22.add(shBtn2);
p22.add(submitBtn);
p22.add(
new
JLabel());
p22.add(
new
JLabel());

p2.add(p20,
"
North
"
);
p2.add(p21,
"
Center
"
);
p2.add(p22,
"
South
"
);

mainTab.addTab(
"
按键式
"
, p1);
mainTab.addTab(
"
表达式
"
, p2);
}
/** */
/**
* init the result-holding dialog
*
*/
private
void
initHolder()
{
resultHolder
=
new
JDialog();
resultHolder.setTitle(
"
计算结果记录
"
);
resultHolder.setLocation(
this
.getLocation().x
+
this
.getWidth()
+
10
,
this
.getLocation().y);
resultList
=
new
JList();
resultList.setSize(
150
,
200
);
 resultList.addMouseListener(
new
java.awt.event.MouseAdapter()
{

public
void
mouseClicked(java.awt.event.MouseEvent e)
{

if
(e.getClickCount()
==
2
)
{
String s
=
(String) resultList.getSelectedValue();
//
System.err.print(mainTab.getSelectedIndex());
if
(mainTab.getSelectedIndex()
==
0
)
{
resultField1.setText(s);
completed
=
false
;
}
else
resultField2.setText(s);
}
}
}
);
resultHolder.add(
new
JScrollPane(resultList));
resultHolder.setSize(
150
,
200
);
}
/** */
/**
* the main init method, init the whole application
*
*/
private
void
init()
{
this
.setTitle(
"
DollyCal Calculator
"
);
this
.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
this
.setLayout(
new
BorderLayout());
initReference();
initMenu();
initTabbedPane();
initHolder();
add(menu,
"
North
"
);
add(
new
JScrollPane(mainTab),
"
South
"
);
pack();
setLocation(
200
,
100
);
setVisible(
true
);
}
/** */
/**
* 处理有关系统功能(显示、隐藏结果记录对话框,存储计算结果,清屏,退格)的按键触发事件
*/
public
void
actionPerformed(ActionEvent e)
{
//
TODO Auto-generated method stub
if
(e.getSource().equals(shBtn)
||
e.getSource().equals(shBtn2))
{

if
(resultHolder.isVisible()
==
false
)
{
resultHolder.setLocation(
this
.getLocation().x
+
this
.getWidth()
+
10
,
this
.getLocation().y);
resultHolder.setVisible(
true
);
}
else
resultHolder.setVisible(
false
);
}
if
(e.getSource().equals(saveBtn))
{
resultHolder.setLocation(
this
.getLocation().x
+
this
.getWidth()
+
10
,
this
.getLocation().y);
if
(resultField1.getText()
!=
null
&&
resultField1.getText().length()
>
0
)
{
resultVector.add(
0
, resultField1.getText());
resultList.setListData(resultVector);
resultList.repaint();
}
resultHolder.setVisible(
true
);
}
if
(e.getSource().equals(saveBtn2)
||
e.getSource().equals(inputField))
{
resultHolder.setLocation(
this
.getLocation().x
+
this
.getWidth()
+
10
,
this
.getLocation().y);
if
(resultField2.getText()
!=
null
&&
resultField2.getText().length()
>
0
)
{
resultVector.add(
0
, resultField2.getText());
resultList.setListData(resultVector);
resultList.repaint();
}
resultHolder.setVisible(
true
);
}
if
(e.getSource().equals(clearBtn))
{
resultField1.setText(
"
0.0
"
);
first
=
true
;
continued
=
false
;
completed
=
false
;
}
if
(e.getSource().equals(backBtn))
{
String s
=
resultField1.getText();

if
(s.length()
>
0
)
{
String t
=
s.substring(
0
, s.length()
-
1
);
if
(t.length()
>
0
&&
t.charAt(t.length()
-
1
)
==
'
.
'
)
t
=
t.substring(
0
, t.length()
-
1
);
resultField1.setText(t);
}
}
}
/** */
/**
* application entry point
*
*
@param
args
*/
public
static
void
main(String[] args)
{
//
TODO Auto-generated method stub
try
{
UIManager.setLookAndFeel(
new
SubstanceLookAndFeel());
UIManager.put(
"
swing.boldMetal
"
,
false
);

if
(System.getProperty(
"
substancelaf.useDecorations
"
)
==
null
)
{
JFrame.setDefaultLookAndFeelDecorated(
true
);
JDialog.setDefaultLookAndFeelDecorated(
true
);
}
//
System.setProperty("sun.awt.noerasebackground", "true");
SubstanceLookAndFeel.setCurrentTheme(
new
SubstancePurpleTheme());
SubstanceLookAndFeel
.setCurrentWatermark(
new
SubstanceBinaryWatermark());
 }
catch
(Exception e)
{
System.err.println(
"
Oops! Something went wrong!
"
);
}
CalculatorFace c
=
new
CalculatorFace();
}
/** */
/**
* 处理数字按键的触发事件
*
*
@author
td
*
*/
private
class
NumberListener
implements
ActionListener
{


public
void
actionPerformed(ActionEvent e)
{
//
TODO Auto-generated method stub
if
(e.getSource()
instanceof
JButton)
{
String s
=
resultField1.getText();
JButton btn
=
(JButton) e.getSource();
String t
=
btn.getText();

if
(completed
||
first)
{
resultField1.setText(t);
first
=
false
;
 }
else
{
resultField1.setText(s
+
t);
}
completed
=
false
;
continued
=
true
;
}
}
}
/** */
/**
* 处理单操作数的运算按键触发事件(包含等号,PI,E)
*
*
@author
td
*
*/
private
class
OneOperatorListener
implements
ActionListener
{


public
void
actionPerformed(ActionEvent e)
{
//
TODO Auto-generated method stub
errorLabel1.setText(
""
);
JButton btn
=
(JButton) e.getSource();
String s
=
resultField1.getText();
String t
=
btn.getText();

if
(t.equals(
"
+/-
"
))
{

if
(completed
||
first)
{
completed
=
false
;
resultField1.setText(
"
-
"
);
}
}
if
(t.equals(
"
.
"
))
{

if
(completed
||
first)
{
completed
=
false
;
resultField1.setText(
"
0.
"
);
 }
else
{
if
(s.indexOf(
"
.
"
)
==
-
1
)
resultField1.setText(s
+
"
.
"
);
}
}
if
(t.equals(
"
PI
"
))
{

if
(completed
||
first)
{
;
resultField1.setText(String.valueOf(Math.PI));
completed
=
false
;
}
}
if
(t.equals(
"
E
"
))
{

if
(completed
||
first)
{
resultField1.setText(String.valueOf(Math.E));
completed
=
false
;
}
}
if
(t.equals(
"
!
"
))
{

try
{
int
i
=
Integer.parseInt(s);
int
n
=
1
;

for
(
int
j
=
1
; j
<=
i; j
++
)
{
n
*=
j;
}
resultField1.setText(String.valueOf(n));
completed
=
true
;
 }
catch
(NumberFormatException nfe)
{
errorLabel1.setText(
"
小数不能做阶乘运算
"
);
completed
=
true
;
}
}
if
(t.equals(
"
1/x
"
))
{
double
d
=
Double.parseDouble(s);
resultField1.setText(String.valueOf(
1
/
d));
completed
=
true
;
}
if
(t.equals(
"
ln
"
))
{
double
d
=
Double.parseDouble(s);
resultField1.setText(String.valueOf(Math.log(d)));
completed
=
true
;
}
if
(t.equals(
"
log
"
))
{
double
d
=
Double.parseDouble(s);
resultField1.setText(String.valueOf(Math.log10(d)));
completed
=
true
;
}
if
(t.equals(
"
sin
"
))
{
double
d
=
Double.parseDouble(s);
resultField1.setText(String.valueOf(Math.sin(d)));
completed
=
true
;
}
if
(t.equals(
"
cos
"
))
{
double
d
=
Double.parseDouble(s);
resultField1.setText(String.valueOf(Math.cos(d)));
completed
=
true
;
}
if
(t.equals(
"
tan
"
))
{
double
d
=
Double.parseDouble(s);
resultField1.setText(String.valueOf(Math.tan(d)));
completed
=
true
;
}
if
(t.equals(
"
cot
"
))
{
double
d
=
Double.parseDouble(s);
resultField1.setText(String.valueOf(
1
/
Math.tan(d)));
completed
=
true
;
}
if
(t.equals(
"
arcsin
"
))
{
double
d
=
Double.parseDouble(s);
resultField1.setText(String.valueOf(Math.asin(d)));
completed
=
true
;
}
if
(t.equals(
"
arccos
"
))
{
double
d
=
Double.parseDouble(s);
resultField1.setText(String.valueOf(Math.acos(d)));
completed
=
true
;
}
if
(t.equals(
"
arctan
"
))
{
double
d
=
Double.parseDouble(s);
resultField1.setText(String.valueOf(Math.atan(d)));
completed
=
true
;
}
if
(t.equals(
"
arccot
"
))
{
double
d
=
Double.parseDouble(s);
resultField1
.setText(String.valueOf(Math.PI
/
2
-
Math.atan(d)));
completed
=
true
;
}
if
(t.equals(
"
=
"
))
{
number1
=
number2;
number2
=
resultField1.getText();
System.out.print(lastOperator);
if
(lastOperator
!=
null
)
operator(lastOperator);
completed
=
true
;
lastOperator
=
""
;
}
first
=
false
;
}
}
/** */
/**
* 处理双操作数的运算按键触发事件
*
*
@author
td
*
*/
private
class
TwoOperatorListener
implements
ActionListener
{


public
void
actionPerformed(ActionEvent e)
{
//
TODO Auto-generated method stub
if
(continued
||
first)
{
number1
=
number2;
errorLabel1.setText(
""
);
JButton btn
=
(JButton) e.getSource();
String s
=
resultField1.getText();
System.err.println(s);
number2
=
s;
String t
=
btn.getText();
if
(lastOperator
!=
null
)
operator(lastOperator);
lastOperator
=
t;
first
=
false
;
completed
=
true
;
continued
=
false
;
 }
else
{
JButton btn
=
(JButton) e.getSource();
String t
=
btn.getText();
lastOperator
=
t;
}
}
}
/** */
/**
* 执行双操作数的运算
*
*
@param
t
*/
private
void
operator(String t)
{

if
(t.equals(
"
+
"
))
{
double
a
=
Double.parseDouble(number1);
double
b
=
Double.parseDouble(number2);
resultField1.setText(String.valueOf(a
+
b));
}
if
(t.equals(
"
-
"
))
{
double
a
=
Double.parseDouble(number1);
double
b
=
Double.parseDouble(number2);
resultField1.setText(String.valueOf(a
-
b));
}
if
(t.equals(
"
*
"
))
{
double
a
=
Double.parseDouble(number1);
double
b
=
Double.parseDouble(number2);
resultField1.setText(String.valueOf(a
*
b));
}
if
(t.equals(
"
/
"
))
{
double
a
=
Double.parseDouble(number1);
double
b
=
Double.parseDouble(number2);
resultField1.setText(String.valueOf(a
/
b));
}
if
(t.equals(
"
%
"
))
{
double
a
=
Double.parseDouble(number1);
double
b
=
Double.parseDouble(number2);
resultField1.setText(String.valueOf(a
%
b));
}
if
(t.equals(
"
^
"
))
{
double
a
=
Double.parseDouble(number1);
double
b
=
Double.parseDouble(number2);
resultField1.setText(String.valueOf(Math.pow(a, b)));
}
number2
=
resultField1.getText();
}
/** */
/**
* 处理表达式输入框回车以及确定键的触发事件,将调用Parser解析并计算表达式
*
@author
td
*
*/
private
class
ParserListener
implements
ActionListener
{


public
void
actionPerformed(ActionEvent e)
{
//
TODO Auto-generated method stub
variables
=
variableArea.getText();
express
=
inputField.getText();
//
deal with variables
if
(variables
!=
null
&&
express
!=
null
)
{
String ss[]
=
variables.split(
"
,
"
);

for
(String s : ss)
{
String v[]
=
s.split(
"
=
"
);
if
(v.length
==
2
)
express
=
parser.replaceExpress(express, v[
0
],
getNumber(v[
1
]));
}
}
try
{
result2
=
parser.entry(express);
errorLabel2.setText(
""
);
resultField2.setText(Double.toString(result2));
 }
catch
(ParserException e1)
{
//
TODO Auto-generated catch block
errorLabel2.setText(e1.toString());
}
}
//
only get the digital part of the variables' values
public
String getNumber(String s)
{
StringBuffer sb
=
new
StringBuffer(s);
StringBuffer tmp
=
new
StringBuffer();

for
(
int
i
=
0
; i
<
s.length(); i
++
)
{

if
(Character.isDigit(sb.charAt(i))
||
sb.charAt(i)
==
'
.
'
)
{
tmp.append(sb.charAt(i));
}
}
return
tmp.length()
>
0
?
tmp.toString() :
"
1
"
;
}
}
}
package
cn.com.w4t.calculator;

import
java.util.ArrayList;
import
java.util.List;


/** */
/**
* Express Parser
*
*
@author
td
*
*/
public
class
Parser
{
//
Define the end of expression
private
final
String EOE
=
"
\0
"
;

//
These are the types of tokens
private
final
int
NONE
=
0
;

private
final
int
DELIMITER
=
1
;

private
final
int
VARIABLE
=
2
;

private
final
int
NUMBER
=
3
;

//
These are the errors of SYNTAX
private
final
int
SYNTAX
=
0
;

private
final
int
UNBALPARENTH
=
1
;

private
final
int
NOEXP
=
2
;

private
final
int
DIVBYZERO
=
3
;

//
Array for variables
private
double
var[]
=
new
double
[
26
];

//
Define the variables
private
String exp;
//
Expression user entered
private
int
expIdx;
//
The index of the expression
private
int
tokType;
//
Type of the current token
private
String token;
//
The current token
private
static
List
<
String
>
operatorList;

static
{
operatorList
=
new
ArrayList
<
String
>
();
operatorList.add(
"
sin
"
);
operatorList.add(
"
cos
"
);
operatorList.add(
"
tan
"
);
operatorList.add(
"
cot
"
);
operatorList.add(
"
arcsin
"
);
operatorList.add(
"
arccos
"
);
operatorList.add(
"
arccot
"
);
operatorList.add(
"
ln
"
);
operatorList.add(
"
arctan
"
);
operatorList.add(
"
log
"
);
}
/** */
/**
* judge wether the token is Delimiter
*
*
@param
tok
* the token
*
@return
the judgement
*/
private
boolean
isDelim(
char
tok)
{
if
(
"
+-*/%^()
"
.indexOf(tok)
!=
-
1
)
return
true
;
return
false
;
}
/** */
/**
* check the token wether a operator it is
*
*
@param
tok
* the token
*
@return
the judgement
*/
private
boolean
isOperator(String tok)
{
return
operatorList.contains(tok);
}
//
The method getToken(),it can get next tokens
/** */
/**
* get the basic element of the express
*/
private
void
getToken()
{
//
System.out.println("gettoken");
token
=
""
;
tokType
=
NONE;

if
(expIdx
==
exp.length())
{
//
If end of expression the token=EOE
token
=
EOE;
return
;
}
while
(expIdx
<
exp.length()
&&
Character.isWhitespace(exp.charAt(expIdx)))
++
expIdx;
//
Removing the whitespace from the token
if
(expIdx
==
exp.length())
{
//
After removing,judge whether the end
//
of expression
token
=
EOE;
return
;
}
if
(isDelim(exp.charAt(expIdx)))
{
//
is operator
token
=
token
+
exp.charAt(expIdx);
tokType
=
DELIMITER;
expIdx
++
;
 }
else
if
(Character.isLetter(exp.charAt(expIdx)))
{
//
is Letter
while
(
!
isDelim(exp.charAt(expIdx))

&&
Character.isLetter(exp.charAt(expIdx)))
{
token
=
token
+
exp.charAt(expIdx);
expIdx
++
;
if
(expIdx
==
exp.length())
break
;
if
(isOperator(token))
break
;
}
if
(isOperator(token))
tokType
=
DELIMITER;

else
{

while
(expIdx
<
exp.length()
&&
!
isDelim(exp.charAt(expIdx)))
{
token
=
token
+
exp.charAt(expIdx);
expIdx
++
;
if
(expIdx
==
exp.length())
break
;
}
tokType
=
VARIABLE;
}
}
else
if
(Character.isDigit(exp.charAt(expIdx)))
{
//
is digital
while
(
!
isDelim(exp.charAt(expIdx)))
{
token
=
token
+
exp.charAt(expIdx);
expIdx
++
;
if
(expIdx
==
exp.length())
break
;
}
tokType
=
NUMBER;
 }
else
{
token
=
EOE;
//
end of expression
return
;
}
}
private
void
handleErr(
int
error)
throws
ParserException
{
 String[] err
=
{
"
表达式语法错误
"
,
"
表达式括号未平衡
"
,
"
表达式为空
"
,
"
除0错误
"
}
;
throw
new
ParserException(err[error]);
}
/** */
/**
* handling errors
*
*
@param
error
* the error
*
@throws
ParserException
*/
private
void
handleErr(String error)
throws
ParserException
{
throw
new
ParserException(error);
}
//
get the old token
//
private void getBack() {
//
if (token == EOE)
//
return;
//
for (int i = 0; i < token.length(); i++)
//
--expIdx;
//
}

//
The main course starts
//
The entry is the programme's entry,everything will be processed through
//
it
/** */
/**
* The entry is the programme's entry,everything will be processed through
* it
*/
public
double
entry(String expstr)
throws
ParserException
{
double
result;
exp
=
expstr;
expIdx
=
0
;
getToken();

if
(token.equals(EOE))
handleErr(NOEXP);

result
=
expCal1();

if
(
!
token.equals(EOE))
handleErr(SYNTAX);

return
result;

}
//
expCal1 process VARIABLE
private
double
expCal1()
throws
ParserException
{
return
expCal2();
}
/** */
/**
* process add and substract
*/
private
double
expCal2()
throws
ParserException
{
double
result;
char
op;
double
partialResult;
//
System.out.println("2");
result
=
expCal3();


while
((op
=
token.charAt(
0
))
==
'
+
'
||
op
==
'
-
'
)
{
//
System.out.println("2while");
getToken();
partialResult
=
expCal3();

switch
(op)
{
case
'
+
'
:
result
=
result
+
partialResult;
break
;
case
'
-
'
:
result
=
result
-
partialResult;
break
;
default
:
handleErr(SYNTAX);
break
;
}
}
return
result;

}
/** */
/**
* process multiply and divide
*/
private
double
expCal3()
throws
ParserException
{
char
op;
double
result;
double
partialResult;
//
System.out.println("3");
result
=
expCal4();

while
((op
=
token.charAt(
0
))
==
'
/
'
||
op
==
'
*
'
||
op
==
'
%
'
)
{
//
System.out.println("3while");
getToken();
partialResult
=
expCal4();

switch
(op)
{
case
'
/
'
:
if
(partialResult
==
0.0
)
handleErr(DIVBYZERO);
result
=
result
/
partialResult;
break
;
case
'
*
'
:
result
=
result
*
partialResult;
break
;
case
'
%
'
:
if
(partialResult
==
0.0
)
handleErr(DIVBYZERO);
result
=
result
%
partialResult;
break
;
}
}
return
result;

}
/** */
/**
* process ^ operater
*/
private
double
expCal4()
throws
ParserException
{
double
result;
double
partialResult;
double
tempRe;
//
System.out.println("4");
result
=
expCal5();
tempRe
=
result;

while
(token.charAt(
0
)
==
'
^
'
)
{
System.out.println(
"
4while
"
);
getToken();
partialResult
=
expCal4();
if
(partialResult
==
0.0
)
result
=
1.0
;
else
result
=
Math.pow(result, partialResult);
}
return
result;
}
/** */
/**
* process sin,cos,tan,cot,arcsin,arccos,arctan,arccot,log,ln
*/
private
double
expCal5()
throws
ParserException
{
double
result;
String op
=
""
;
if
(tokType
==
DELIMITER
&&
(op
=
token).equals(
"
sin
"
)
||
op.equals(
"
cos
"
)
||
op.equals(
"
tan
"
)
||
op.equals(
"
cot
"
)
||
op.equals(
"
arctan
"
)
||
op.equals(
"
arccot
"
)
||
op.equals(
"
arcsin
"
)
||
op.equals(
"
arccos
"
)
||
op.equals(
"
ln
"
)
||
op.equals(
"
log
"
))
getToken();
result
=
expCal6();
if
(op.equals(
"
sin
"
))
result
=
Math.sin(result);
if
(op.equals(
"
cos
"
))
result
=
Math.cos(result);
if
(op.equals(
"
tan
"
))
result
=
Math.tan(result);
if
(op.equals(
"
cot
"
))
result
=
1
/
Math.tan(result);
if
(op.equals(
"
arcsin
"
))
result
=
Math.asin(result);
if
(op.equals(
"
arccos
"
))
result
=
Math.acos(result);
if
(op.equals(
"
arctan
"
))
result
=
Math.atan(result);
if
(op.equals(
"
arccot
"
))
result
=
Math.PI
/
2
-
Math.atan(result);
if
(op.equals(
"
ln
"
))
result
=
Math.log(result);
if
(op.equals(
"
log
"
))
result
=
Math.log10(result);
return
result;
}
/** */
/**
* process unary +,-
*/
private
double
expCal6()
throws
ParserException
{
double
result;
String op
=
""
;
if
(tokType
==
DELIMITER
&&
(op
=
token).equals(
"
+
"
)
||
op.equals(
"
-
"
))
getToken();
result
=
expCal7();
if
(op.equals(
"
-
"
))
result
=
-
result;

return
result;
}
//
process parenthesized expression
/** */
/**
* process parenthesized expression
*/
private
double
expCal7()
throws
ParserException
{
double
result;
//
System.out.println("7");
if
(token.equals(
"
(
"
))
{
//
System.out.println("6if");
getToken();
result
=
expCal2();
if
(
!
token.equals(
"
)
"
))
handleErr(UNBALPARENTH);
getToken();
 }
else
if
((tokType
==
DELIMITER))
{
getToken();
result
=
expCal2();
}
else
result
=
expCal8();
//
System.err.println(result);
return
result;
}
//
convert String to NUMBER
/** */
/**
* convert String to NUMBER
*/
private
double
expCal8()
throws
ParserException
{
double
result
=
0.0
;
//
System.out.println("8");
switch
(tokType)
{
case
VARIABLE:
result
=
findVar();
getToken();
break
;
case
NUMBER:

try
{
char
c
=
token.charAt(token.length()
-
1
);

if
(c
==
'
!
'
)
{
String s
=
token.substring(
0
, token.length()
-
1
);
if
(s.indexOf(
"
.
"
)
!=
-
1
)
handleErr(
"
只能对整数进行阶乘运算
"
);

else
{
result
=
Integer.parseInt(s);
double
n
=
1.0
;

for
(
int
i
=
1
; i
<=
result; i
++
)
{
n
=
n
*
i;
}
result
=
n;
}
}
else
result
=
Double.parseDouble(token);
 }
catch
(NumberFormatException exc)
{
handleErr(SYNTAX);
}
getToken();
break
;
default
:
handleErr(SYNTAX);
break
;
}
return
result;
}
private
double
findVar()
throws
ParserException
{

if
(
!
Character.isLetter(token.charAt(
0
)))
{
handleErr(SYNTAX);
return
0.0
;
}
handleErr(token
+
"
未赋值
"
);
return
var[Character.toLowerCase(token.charAt(
0
))
-
'
a
'
];

}
/** */
/**
* replace the variable with its value
*
*
@param
express
* the initial express
*
@param
name
* the variable's name
*
@param
value
* the variable's value
*
@return
replaced express
*/
public
String replaceExpress(String express, String name, String value)
{
token
=
""
;
expIdx
=
0
;
exp
=
express;
StringBuffer tmp
=
new
StringBuffer();
if
(express
==
null
||
express.length()
<
1
)
return
express;

while
(
!
token.equals(
"
\0
"
))
{

if
(token.length()
>
0
&&
token.charAt(token.length()
-
1
)
==
'
!
'
)
{
String s
=
token.substring(
0
, token.length()
-
1
);
if
(s.equals(name))
s
=
value;
tmp.append(s);
tmp.append(
"
!
"
);
 }
else
{
if
(token.equals(name))
token
=
value;
tmp.append(token);
}
getToken();
}
return
tmp.toString();
}
}
/** */
/**
* errors that occured in calculating
*
*
@author
td
*
*/
class
ParserException
extends
Exception
{
static
final
long
serialVersionUID
=
314088734511860866L
;

private
String str;


public
ParserException(String str)
{
this
.str
=
str;
}
public
String toString()
{
return
str;
}
}
评论:
-
# re: 自己做的多功能计算器,嘿嘿
Posted @ 2006-11-24 19:04
顶一下先! 回复 更多评论
-
# re: 自己做的多功能计算器,嘿嘿
Posted @ 2006-11-25 12:39
界面很好看,写的不错 回复 更多评论
-
# re: 自己做的多功能计算器,嘿嘿
Posted @ 2006-11-26 21:53
恩 不错
支持一下,我以前也做过一个,不过那个和window的差不多 回复 更多评论
-
# re: 自己做的多功能计算器,嘿嘿
Posted @ 2006-11-27 17:32
还差一点就完美了:
应该写个运行该程序的 bat(windows) 和 sh(linux) 回复 更多评论
-
# re: 自己做的多功能计算器,嘿嘿
Posted @ 2006-11-27 18:48
@windows计算器坏了
写了
没提交上来,还有本地exe,呵呵 回复 更多评论
-
# re: 自己做的多功能计算器,嘿嘿
Posted @ 2007-01-24 20:07
你好,我想运行一下你的这个程序,可以提供一下下面那三个包吗
org.jvnet.substance.SubstanceLookAndFeel
org.jvnet.substance.theme.SubstancePurpleTheme
org.jvnet.substance.watermark.SubstanceBinaryWatermark 回复 更多评论
-
# re: 自己做的多功能计算器,嘿嘿
Posted @ 2007-09-10 08:41
不知道怎么运行啊 回复 更多评论
-
# re: 自己做的多功能计算器,嘿嘿
Posted @ 2007-12-27 09:01
我也在做这个,但没你那个好看,还是遇到问题了,是技术不佳,可以请教一下吗 回复 更多评论
-
# re: 自己做的多功能计算器,嘿嘿
Posted @ 2008-03-23 14:49
谢谢 回复 更多评论
-
# re: 自己做的多功能计算器,嘿嘿[未登录]
Posted @ 2008-07-06 12:14
你这程序有调试么? 回复 更多评论
|