1.写一个简单的数学表达式函数,只需支持+,-,*,/,(,).括号有可能是嵌套,运算符优先级。如输入“((1+3)*3+(2+2)*5)/4”能得出结果8
2.计算出1000的阶乘(不能用科学计数法和Math类)

解决方案 »

  1.   

    第二题考虑一下大数就可以了.
    第一题我以前做过:
    //本程序只能计算正整数范围内的加减乘除运算。
    import java.util.*;public class Expression{
    //优先级数组,precede[i][j],表示第i个操作符与第j个操作符的优先级,0,1,2,3,4,5,6分别是'+', '-', '*', '/', '(', ')', '#'
    //0表示,第i个操作符优先级小于第j个操作符。1表示大于,2表示相等,3是表示不可能的。
    int precede[][]={{1 , 1 , 0 , 0 , 0 , 1 , 1},
                         {1 , 1 , 0 , 0 , 0 , 1 , 1},
                         {1 , 1 , 1 , 1 , 0 , 1 , 1},
                         {1 , 1 , 1 , 1 , 0 , 1 , 1},
                         {0 , 0 , 0 , 0 , 0 , 2 , 3},
                         {1 , 1 , 1 , 1 , 3 , 1 , 1},
                         {0 , 0 , 0 , 0 , 0 , 3 , 2}};
        char[] operate={'+', '-', '*', '/', '(', ')', '#'};
        String exp=null;
        public Expression(String exp){
         this.exp=exp;
        }
    int getValueInt(){
    Stack<Integer> optr=new Stack<Integer>();
    Stack<Integer> opnd=new Stack<Integer>();
    String expression=exp+"#";          //给表达式加一个运算符,且是一个结束符
    optr.push(6);                     //先把'#'操作符对应的序号入栈。
    int index=0;                      //从0开始扫描表达式字符串。
    //int sign=1;                       //符号,假设为正
    int num=0;
    char c=expression.charAt(index++);
    while(c!='#'||optr.peek()!=6){
    if(indexOperate(c)==-1){
    /*if(c=='-'){
    sign=-1;
    c=expression.charAt(index++);
    }else if(c=='+'){
    c=expression.charAt(index++);
    }*/
    while(c>='0'&&c<='9'){
    num=num*10+c-'0';
    c=expression.charAt(index++);
    }
    opnd.push(num);
    //sign=1;
    num=0;
    }
    if(indexOperate(c)==-1){
    System.out.println("Expression is Error!");
    System.exit(0);
    }
    switch(precede[optr.peek()][indexOperate(c)]){
    case 0 : 
    optr.push(indexOperate(c));
    c=expression.charAt(index++);
    break;
    case 1 :
    int num2=opnd.pop();
    int opt=optr.pop();
    int num1=opnd.pop();
    opnd.push(binaryOperation(num1,opt,num2));
    break;
    case 2 :
    optr.pop();
    c=expression.charAt(index++);
    break;
    case 3 :
    System.out.println("括号不配对Expression Error!");
    System.exit(0);
    }//switch
    }//while
    return opnd.peek();
    }
    int indexOperate(char c){
    for(int i=0;i<operate.length;i++){
    if(operate[i]==c) return i;
    }
    return -1;
    }
    int binaryOperation(int operand1,int opt,int operand2 ){
    switch(opt){
    case 0:
    return operand1+operand2;
    case 1:
    return operand1-operand2;
    case 2:
    return operand1*operand2;
    case 3:
    return operand1/operand2;
    }
    return 0;
    }
    public static void main(String[] args){
    Expression e=new Expression("((1+3)*3+(2+2)*5)/4");
    //Expression e=new Expression("1+5");
    System.out.println(e.getValueInt()); }
    }
      

  2.   


    public int factorial(int x) {        if (x < 0) {            throw new IllegalArgumentException("x must be>=0");        }        int fact = 1;        for (int i = 2; i <= x; i++) {            fact *= i;        }        return fact;    }
      

  3.   

    BigInteger是Math里的   他规定不可以用 
      

  4.   

    int 只能表示2的32此方,1000的阶层应当大于这个
    BigDecimel 表示范围
      

  5.   

    .计算出1000的阶乘(不能用科学计数法和Math类)用BigInteger就可以了.
    不让用Math类,可以用java.math包中的BigInteger类.Math类是指java.lang.Math
      

  6.   


     public static BigInteger fac(BigInteger x) {
         if (x.intValue()==1) {
         return BigInteger.ONE;
         } else {
         BigInteger b = x.subtract(BigInteger.ONE);
         return x.multiply(fac(b));
         }
        }
      

  7.   

    http://topic.csdn.net/u/20090804/03/e812a63a-92c1-49d1-a4c0-6b2888b1dc8a.html这个贴子中,火龙果的求阶乘算法最好!
      

  8.   

    第一题需要用递归下降法!!见《java编程艺术》一书,经典的问题了!
      

  9.   

    第一题:数据结构(二叉树)
    第二题:数论(模拟大数计算)
    package Helloworld;public class Hello {
    public static void main(String args[]) {
    int TheNumber = 1111;/*--- 要求阶乘的数字---*/
    int mod = 10000;
    int[] ary = new int[TheNumber];
    ary[0] = 1;

    int i, j;
    int width; /*---表示结果的"宽度"---*/
    int current_num; /*--- 当前数字 ---*/

    /*--- 从大到小进行阶乘计算 ---*/
    for( width = 0 , current_num = TheNumber ; current_num > 1; current_num-- ){

    /*--- 对每一个‘分段’进行运算 ---*/
    for( i = j = 0; i <= width; i++ ){

    /*--- 当前运算的‘有效数值’ ---*/
    ary[i] = ( (j += ary[i] * current_num) ) % mod;

    /*--- 当前运算的‘进位数值’ ---*/
    j /= mod;   
    }  
    if ( (ary[i] = j ) != 0){ /*如果有进位,则索引向前推进*/
    width++;   
    }
    }   /*--- 将求的数值输出 ---*/
    System.out.printf("%d", ary[width] );  

    /*--- 将求的数值输出 ---*/
    for( j = width - 1; j >= 0; j-- ){

    System.out.printf( "%04d", ary[j] );/*--- 这里的4跟mod的位数有关 ---*/
    }  
    }
    }
      

  10.   

    我们来考虑另外一种方案,将乘积的每一位数字都存放在数组中,这样的话一个长度为10000的数组可以存放任何一个10000位以内的数字。 假设数组为uint[] array = new uint[10000],因为1! = 1,所以首先置a[0] = 1,分别乘以2、3,得到3! = 6,此时仍只需要一个元素a[0];然后乘以4得到24,我们把个位数4放在a[0],十位数2放在a[1],这样存放结果就需要两个元素;乘以5的时候,我们可以这样进行:用5与各元素由低到高逐一相乘,先计算个位数(a[0])4 × 5,结果为20,这样将a[0]置为0,注意要将2进到十位数,然后计算原来的十位数(a[1])2 × 5,结果为10加上刚才进的2 为12,这样十位数是2,而1则进到百位,这样就得到5! = 120;以此类推…… 下面给出上述方案的一个实现: 
    public static uint[] CalculateLargeNumber(int n)
    {
        if (n < 0) { throw new ArgumentOutOfRangeException("n必须为非负数。"); }    if (n == 0 || n == 1) { return new uint[] { 1 }; }
        // 数组的最大长度
        const int MaxLength = 100000;
        uint[] array = new uint[MaxLength];
        // 1! = 1
        array[0] = 1;
        int i = 0;
        int j = 0;
        // valid为当前阶乘值的位数(如5! = 120,此时valid = 3)
        int valid = 1;    for (i = 2; i <= n; i++)
        {
            long carry = 0;
            for (j = 0; j < valid; j++)
            {
                long multipleResult = array[j] * i + carry;
                // 计算当前位的数值
                array[j] = (uint)(multipleResult % 10);
                // 计算进到高位的数值
                carry = multipleResult / 10;
            }
            // 为更高位赋值
            while (carry != 0)
            {
                array[valid++] = (uint)(carry % 10);
                carry /= 10;
            }
        }
        // 截取有效元素
        uint[] result = new uint[valid];
        Array.Copy(array, result, valid);
        return result;

    用这个方法可以得出70!是101位(1.1979 × 10^100),450!是1001位,而1000!有2568位。需要注意的是,结果数的最高位存放在数组的索引最大的元素中,所以打印结果时要按正确的顺序。
      

  11.   

    我们来考虑另外一种方案,将乘积的每一位数字都存放在数组中,这样的话一个长度为10000的数组可以存放任何一个10000位以内的数字。 假设数组为uint[] array = new uint[10000],因为1! = 1,所以首先置a[0] = 1,分别乘以2、3,得到3! = 6,此时仍只需要一个元素a[0];然后乘以4得到24,我们把个位数4放在a[0],十位数2放在a[1],这样存放结果就需要两个元素;乘以5的时候,我们可以这样进行:用5与各元素由低到高逐一相乘,先计算个位数(a[0])4 × 5,结果为20,这样将a[0]置为0,注意要将2进到十位数,然后计算原来的十位数(a[1])2 × 5,结果为10加上刚才进的2 为12,这样十位数是2,而1则进到百位,这样就得到5! = 120;以此类推…… 下面给出上述方案的一个实现: public static uint[] CalculateLargeNumber(int n)
    {
        if (n < 0) { throw new ArgumentOutOfRangeException("n必须为非负数。"); }    if (n == 0 || n == 1) { return new uint[] { 1 }; }
        // 数组的最大长度
        const int MaxLength = 100000;
        uint[] array = new uint[MaxLength];
        // 1! = 1
        array[0] = 1;
        int i = 0;
        int j = 0;
        // valid为当前阶乘值的位数(如5! = 120,此时valid = 3)
        int valid = 1;    for (i = 2; i <= n; i++)
        {
            long carry = 0;
            for (j = 0; j < valid; j++)
            {
                long multipleResult = array[j] * i + carry;
                // 计算当前位的数值
                array[j] = (uint)(multipleResult % 10);
                // 计算进到高位的数值
                carry = multipleResult / 10;
            }
            // 为更高位赋值
            while (carry != 0)
            {
                array[valid++] = (uint)(carry % 10);
                carry /= 10;
            }
        }
        // 截取有效元素
        uint[] result = new uint[valid];
        Array.Copy(array, result, valid);
        return result;

    用这个方法可以得出70!是101位(1.1979 × 10^100),450!是1001位,而1000!有2568位。需要注意的是,结果数的最高位存放在数组的索引最大的元素中,所以打印结果时要按正确的顺序。
      

  12.   

    public static BigDecimal hierarchy(BigDecimal num) {

    if(num == BigDecimal.ONE) {
    return BigDecimal.ONE;
    } else {
    return num.multiply(hierarchy(num.subtract(BigDecimal.ONE)));
    }
    }
      

  13.   

    根据37的算法,编的程序,通过验证:
    #include <iostream>
    using namespace std;int a[10000];void Print( int nNum )
    {
    a[0]=1; if ( nNum == 1 )
    {
    return;
    } for ( int j = 2;j <=nNum;j++ )
    {
    int b[2]; memset(b,0,sizeof(b)); for ( int i = 0 ;i < sizeof(a)/sizeof(int);i++ )
    {
    a[i] = a[i]*j + b[1];
    b[1] = 0;//加了后立刻置0,很关键
    if ( a[i] < 10 )
    {
    b[0] = a[i];
    }
    else
    {
    b[0] = a[i]%10;
    b[1] = (a[i]-b[0])/10;
    a[i] = b[0];
    b[0] = 0;
    }
    }
    }
    }void main()
    {
    int nNum ;
    while(true)
    {
    memset(a,0,sizeof(a));
    cout<<"please input a Integer Number:";
    cin>>nNum;
    if ( nNum <= 0 )
    {
    continue;
    } Print(nNum); //打印输出
    bool bl = false;
    for ( int i = sizeof(a)/sizeof(int)-1 ;i >= 0;i-- )
    {
    if ( a[i] != 0 || bl)
    {
    cout<<a[i];
    bl = true;
    }
    }
    cout<<"\n";
    }
    }
      

  14.   


    public static void main(String str[]) {          int[] res = new int[3000];          final int limit = 1000;                    res[1] = 1; 
     int max_now = 1;           for(int step = 1; step <= limit;step++)          {                      int temp = 0;              int now = max_now;     //40320              int zero;              for(zero = 1; zero <=now;zero++)          {                  if(res[zero] != 0)                      break;              }                            for(int carry = zero-1;carry <= now;carry++)              {                  res[carry] *= step;                  res[carry] += temp;                     temp = 0;                 if(res[carry] >= 10)                 {                      int carry_temp = carry;                      temp = res[carry];                      if(carry_temp <= max_now)                      {                          res[carry_temp] = temp%10;                          temp/=10;                          carry_temp++;                      }                      if(carry_temp > max_now)                      {                       while(temp >= 10)                          {                              res[carry_temp] = temp%10;                              temp /= 10;                              carry_temp++;                          }                          res[carry_temp] = temp;                          temp = 0;                          max_now = carry_temp;                      }                 }              }                              }          System.out.println(max_now);          for(int j = max_now; j > 0; j--)          {              System.out.print(res[j]);          }   } 
      

  15.   


    public static void main(String args[]) 
    {
            int b=1000;             //要计算的数
    int temp=0; //用于最后去掉整个数组中的前面没用的 0
    int tt=0; //用于记录每次乘的进位数;
    int[] a=new int[9000];  //
    a[8999]=1; //把数组最后一位设为了1,从最后一位开始乘,
    for(int i=1;i<=b;i++) //用从 1 到 b 的每一个数去乘数组的每个元素,
    {
    for(int j=8999;j>=0;j--)
    {
    a[j]=a[j]*i+tt;    //数组中的元素=原来的数*i+进位数,
    tt=0; //进位数清0,用于下回记录;
    if((a[j]+"").length()>=2) //此元素大于10则进位,本身只保留余数;
    {
    tt=a[j]/10;
    a[j]=a[j]%10;
    }

    }
    }
    for(int i=0;i<a.length;i++)//去掉数组前的0000
    {
    if(a[i]!=0)
    {
    temp=i;
    break;
    }
    }
    for(int i=temp;i<a.length;i++)//输出
    {
    System.out.print(a[i]);
    }
    }
      

  16.   

    第一题: 用后缀表达式来做://本程序可以实现实数的加减乘除四则运算,
    import java.util.*;
    import java.util.regex.*;
    /**
    *
    */
    public class Expression{
    //优先级数组,precede[i][j],表示第i个操作符与第j个操作符的优先级,0,1,2,3,4,5,6分别是'+', '-', '*', '/', '(', ')', '#'
    //0表示,第i个操作符优先级小于第j个操作符。1表示大于,2表示相等,3是表示不可能的。
    private int precede[][]={{1 , 1 , 0 , 0 , 0 , 1 , 1},
     {1 , 1 , 0 , 0 , 0 , 1 , 1},
     {1 , 1 , 1 , 1 , 0 , 1 , 1},
     {1 , 1 , 1 , 1 , 0 , 1 , 1},
     {0 , 0 , 0 , 0 , 0 , 2 , 3},
     {1 , 1 , 1 , 1 , 3 , 1 , 1},
     {0 , 0 , 0 , 0 , 0 , 3 , 2}};
        private char[] operator={'+', '-', '*', '/', '(', ')', '#'};
        private String infixExpression=null;
        private ArrayList<MetaData> postfixExpression=new ArrayList<MetaData>();
        public Expression(String exp){
         infixExpression=exp+"#";
        }
        /**定义一个内部类表示表达式中的"元数据",操作数,或者是操作符,只能是两者之一.
         *
         *
        */
        private class MetaData{
         double  dData;    //float operand
         int     iData;    // int operand
         char    operator; //operator
         boolean isOperator=false;
        
         MetaData(double dNum){
         dData=dNum;
         }
         MetaData(int iNum){
         iData=iNum;
         }
         MetaData(char operator){
         this.operator=operator;
         isOperator=true;
         }
         public boolean isOperand(){
         return !isOperator;
         }
         public String toString(){
         if(isOperator){
         return ""+operator;
         }else{
         return ""+dData;
         }
         }
        }//end of inner class MetaData
        
        /**由中缀表达式得到后缀表达式。
        *  设一个堆栈,用来存放操作符,先放一个自定义的操作符’#’,它的优先级是最小的。
        *  扫描整个中缀表达式,操作数直接输出到结果postfixExpression中
        *  如果是操作符,就和堆栈栈顶操作符比较,如果栈顶的优先级高则出栈并输出到结果,直到找到优先小的运算符为止。
        *  如果两者优先级相同,表示是配对的括号,或'#'。
        *  把当前的操作入栈。
        */
    private void  getPostfixExp(){
    Stack<Integer> optrStack=new Stack<Integer>();   // Integer is a index of operator.
    int index=0;                                     // index: index of charachter in infixExpression.
    double num=0;                                    //
    char c=0;                                        //
    optrStack.push(6);                               //'#'  index is 6
    //下面的正则用来提取一个数值
    //
    String regex="([-]?[0-9]+(\\.([0-9]+)?)?)";
    Pattern numberPattern=Pattern.compile(regex);
    Matcher numberMatcher=numberPattern.matcher(infixExpression);
    while(index<infixExpression.length()){
    if(numberMatcher.find(index)){
    if(numberMatcher.start()==index){
    num=Double.parseDouble(numberMatcher.group(1));
    postfixExpression.add(new MetaData(num));
    index=numberMatcher.end();
    }
    }
    c=infixExpression.charAt(index++);
    switch(precede[optrStack.peek()][getOperatorOrder(c)]){    //compare operator in stack with operator in c . get precede.
    case 0 :                                              //precede is 0 . means operator'precede in stack small than in c 
    optrStack.push(getOperatorOrder(c));
    break;
    case 1 :
    while(precede[optrStack.peek()][getOperatorOrder(c)]==1){
    postfixExpression.add(new MetaData(operator[optrStack.pop()]));
    }
    if(precede[optrStack.peek()][getOperatorOrder(c)]==2){
    optrStack.pop();       //pop '('
    }else{
    optrStack.push(getOperatorOrder(c));
    }
    break;
    case 2 :
    optrStack.pop();
    break;
    case 3 :
    System.out.println("括号不配对Expression Error!");
    System.exit(0);
    }//switch
    }//while
    }
    /*对后缀表达式求值。
    * 扫描整个后缀表达式,如果是数值,直接入栈。如果是运算符,出栈两个操作数,运算后,再把结果入栈。
    *
    */
    public double evaluate(){
    getPostfixExp();
    Stack<Double> valueStack=new Stack <Double>();
    //System.out.println(postfixExpression);
    for(MetaData md : postfixExpression){
    if(md.isOperand()){
    valueStack.push(md.dData);
    }else{
    double num1=valueStack.pop();
    double num2=valueStack.pop();
    valueStack.push(binaryOperation(num2,getOperatorOrder(md.operator),num1));
    }
    //System.out.println(valueStack);
    }
    return valueStack.pop();
    }
    /*取得操作符的序号,主要是为了比较优先级时,方便的访问precede这个二维数组。
    */
    private int getOperatorOrder(char optr){
     int order;
     switch(optr){
       case '+': order=0; break;
       case '-': order=1; break;
       case '*': order=2; break;
       case '/': order=3; break;
       case '(': order=4; break;
       case ')': order=5; break;
       case '#': order=6; break;
       default : order=-1;
     }
     return order;
    }
        /*对两个操作数据进行运算。
        */
    private double binaryOperation(double operand1,int opt,double operand2 ){
    switch(opt){
    case 0:
    return operand1+operand2;
    case 1:
    return operand1-operand2;
    case 2:
    return operand1*operand2;
    case 3:
    return operand1/operand2;
    }
    return 0;
    }
    public static void main(String[] args){
    Expression e=new Expression("((1+3)*3+(2+2)*5)/-4");
    //Expression e=new Expression("1+5");
    System.out.println(e.evaluate()); }
    }
      

  17.   

    第二题,这么多人写出了不用java类的算法,学习了。求1000!是可以用斯特林公式求出一个近似值的,所以题目要求不用Math类,API中有两个math,一个是java.lang.Math,这个是一个类,用来做各种数学运算的。还有一个是java.math,这是一个包,里面有BigInteger类和BigDecimal类。所以根据题意,用BigInteger的算法,也是正解。