public class Function
{
public String function
public int number_of_arguments
public Function( String function, int number_of_arguments )
{
this.function=function
this.number_of_arguments=number_of_arguments
}
public String toString()
{
return function
}
}
public class Operator
{
public String operator
public byte priority
public Operator( String operator, byte priority )
{
this.operator=operator
this.priority=priority
}
public String toString()
{
return operator
}
}
public class Variable
{
public String variable
public double value
public Variable( String variable, double value )
{
this.variable=variable
this.value=value
}
public String toString()
{
return variable
}
}
Token 类如清单 2 所示。
清单 2. Token 类
public class Token
{
public Object token
public char mark
public int position
public int length
public Token ( Object token, char mark, int position, int length )
{
this.token=token
this.mark=mark
this.position=position
this.length=length
}
public String toString()
{
return token.toString()+" "+mark+" "+position+" "+length+"
"
}
}
清单 3. 三种括号
import java.util.Stack
public class Parentheses_check
{
public static boolean is_open_parenthesis( char c )
{
if ( c=='(' || c=='[' || c=='{' )
return true
else
return false
}
public static boolean is_closed_parenthesis( char c )
{
if ( c==')' || c==']' || c=='}' )
return true
else
return false
}
private static boolean parentheses_match( char open, char closed )
{
if ( open=='(' &&closed==')' )
return true
else if ( open=='[' &&closed==']' )
return true
else if ( open=='{' &&closed=='}' )
return true
else
return false
}
public static boolean parentheses_valid( String exp )
{
Stack s = new Stack()
int i
charcurrent_char
Character c
charc1
boolean ret=true
for ( i=0i <exp.length()i++ )
{
current_char=exp.charAt( i )
if ( is_open_parenthesis( current_char ) )
{
c=new Character( current_char )
s.push( c )
}
else if ( is_closed_parenthesis( current_char ) )
{
if ( s.isEmpty() )
{
ret=false
break
}
else
{
c=(Character)s.pop()
c1=c.charValue()
if ( !parentheses_match( c1, current_char ) )
{
ret=false
break
}
}
}
}
if ( !s.isEmpty() )
ret=false
return ret
}
}
清单 4. 正确的表达式开头的检查
private static boolean begin_check( Vector tokens, Range r, StringBuffer err )
{
char mark
Tokent
t=(Token)tokens.elementAt( 0 )
mark=t.mark
if ( mark=='P' )
err.append( Messages.begin_operator )
else if ( mark==')' )
err.append( Messages.begin_parenthesis )
else if ( mark=='Z' )
err.append ( Messages.begin_comma )
else
return true
r.start=0
r.end=t.length
return false
}
清单 5. 找出第一个闭括号
public static int pos_first_closed_parenthesis( Vector tokens )
{
Token t
for ( int i=0i<tokens.size()i++ )
{
t=(Token)tokens.elementAt( i )
if ( t.mark==')' )
return i
}
return 0
}
清单 6. 找出匹配的开括号
public static int pos_open_parenthesis( Vector tokens, int closed_parenthesis )
{
int i
Tokent
i=closed_parenthesis-2
while ( i>=0 )
{
t=(Token)tokens.elementAt( i )
if ( t.mark=='(' )
{
return i
}
i--
}
return 0
}
清单 7. 找出优先级最高的操作符
public static int pos_operator( Vector tokens, Range r )
{
byte max_priority=Byte.MAX_VALUE
int max_pos=0
byte priority
String operator
Tokent
for ( int i=r.start+2i<=r.end-2i++ )
{
t=(Token)tokens.elementAt( i )
if ( t.mark!='P' )
continue
priority=((Operator)t.token).priority
operator=((Operator)t.token).operator
if ( priority <max_priority || ( operator.equals("^") ||
operator.equals("**") ) &&priority == max_priority )
{
max_priority=priority
max_pos=i
}
}
return max_pos
}
清单 8. 检查是否还有其它操作符
...
int poz_max_op=pos_operator( tokens, range )
// if there are no operators
if ( poz_max_op==0 )
{
if ( no_more_parentheses )
{
return false
}
else
{
double result
result=function_result( tokens, range.start-1 )
function_tokens_removal( tokens, range.start-1 )
t = new Token ( new Double(result), 'D', 0, 0 )
tokens.setElementAt( t, range.start-1 )
parentheses_removal( tokens, range.start-1 )
return true
}
}
...
清单 9. 获取操作数并执行运算...
double operand1, operand2
// first operand is before...
t=(Token)tokens.elementAt( poz_max_op-1 )
operand1=operand_value( t )
// ...and second operand is after operator
t=(Token)tokens.elementAt( poz_max_op+1 )
operand2=operand_value( t )
// operator
t=(Token)tokens.elementAt( poz_max_op )
String op=((Operator)t.token).operator
double result=operation_result( operand1, operand2, op )
tokens.removeElementAt( poz_max_op+1 )
tokens.removeElementAt( poz_max_op )
t = new Token ( new Double(result), 'D', 0, 0 )
tokens.setElementAt( t, poz_max_op-1 )
parentheses_removal( tokens, poz_max_op-1 )
...
清单 10. 获取操作数
public static double operand_value( Token t )
{
if ( t.mark=='V' )
return ((Variable)t.token).value
else if ( t.mark=='D' )
return ((Double)t.token).doubleValue()
else if ( t.mark=='H' )
return base_convert( ((String)t.token).substring(2), 16 )
else if ( t.mark=='O' )
return base_convert( ((String)t.token).substring(2), 8 )
else if ( t.mark=='B' )
return base_convert( ((String)t.token).substring(2), 2 )
}
清单 11. 将数转化为十进制数
public static long base_convert( String s, int base )
{
long r=0
int i, j
for ( i=s.length()-1, j=0i>=0i--, j++ )
r=r+digit_weight( s.charAt( i ) )*(long)Math.pow( base, j )
return r
}
public static int digit_weight( char c )
{
if ( Character.isDigit( c ) )
return c-48
else if ( 'A'<=c &&c<='f' )
return c-55
else if ( 'a'<=c &&c<='f' )
return c-87
return -1
}
清单 13. 除去冗余括号
private static void parentheses_removal( Vector tokens, int pos )
{
if (
pos>1 &&
amp&&
amp
((Token)tokens.elementAt( poz-2 )).mark!='F' &&
amp&&
amp
((Token)tokens.elementAt( poz-1 )).mark=='(' &&
amp&&
amp
((Token)tokens.elementAt( poz+1 )).mark==')'
||
pos==1 &&
amp&&
amp
((Token)tokens.elementAt( 0 )).mark=='(' &&
amp&&
amp
((Token)tokens.elementAt( 2 )).mark==')'
)
{
tokens.removeElementAt( poz+1 )
tokens.removeElementAt( poz-1 )
}
return
}
清单 14. 结合符号并显示结果
public static String token_join( Vector tokens )
{
String result=new String()
Tokent
for ( int i=0i <tokens.size()i++ )
{
t=(Token)tokens.elementAt( i )
if ( t.mark=='D' )
{
double n=((Double)t.token).doubleValue()
result=result + formated_number( n )
}
else
result=result + t.token
if ( result.endsWith( ".0" ) )
result=result.substring( 0, result.length()-2 )
result=result + " "
}
return result
}
结论
本文分析了一个 applet ,它能一步一步的对算术表达式求值。同时还按顺序回顾了最有意思的代码片段,并论述了两种不同的表达式求值方法。
下一版 W3Eval 有望在各方面得到增强,包括有能力添加用户定义的功能;支持分数、复数和矩阵;改良的图形用户界面(GUI);大小和速度优化以及安全性方面的增强。我鼓励您提供您自己对于增强方面的设想。
我希望您会发现 W3Eval 是个对表达式求值有益的在线工具,它在某种程度上比经典的方法更简单自然。我还期待这里谈到的代码和算法使您明白 Java 语言有助于处理数学问题。
!强烈要求加分!
System.out.println("\t" + n + "! = " + compute(n))//调用compute方法,传入参数n}
// 计算n!的方法
static long compute(int n) {
// 1!=1 2!=2*1=2 3!=3*2*1 4!=4*3! ... n!=n*(n-1)!
// 递归: 方法本身含有对自己的调用
if (n == 1) {
return 1
} else {
return n*compute(n-1)//20*compute(20-1)
}
}
lambda表达式是JAVA8中提供的一种新的特性,它支持JAVA也能进行简单的“函数式编程”。它是一个匿名函数,Lambda表达式基于数学中的λ演算得名,直接对应于其中的lambda抽象(lambda abstraction),是一个匿名函数,即没有函数名的函数。
函数式接口:
这个是理解Lambda表达式的重点,也是产生lambda表达式的“母体”,这里我们引用一个比较容易理解的说法:函数式接口是 一个只有一个抽象方法(不包含object中的方法)的接口。
这个需要说明一点,就是在Java中任何一个对象都来自Object 所有接口中自然会继承自Object中的方法,但在判断是否是函数式接口的时候要排除Object中的方法。