欢迎您访问程序员文章站本站旨在为大家提供分享程序员计算机编程知识!
您现在的位置是: 首页

使用plsql开发的计算器程序

程序员文章站 2022-05-07 19:28:49
...

这是一个使用PL SQL开发的计算器程序,实现基本的数学运算。根据提供的数组,展现输入过程,计算出结果。

这个在stanford iphone2011教程的作业的另外一种实现方法。但那个是需要用obj-c实现,我这个是用pl sql实现。

 

这个存储过程中,使用了collection的复杂操作实现计算数据和计算符号的处理,使用递归实现计算的反复调用。

实现 加减程序正弦余弦N次方和N次方根的计算,和输入过程描述。

 

Version 1.1

 

create or replace
PROCEDURE run_science_program_v2
AS
type typ_program
IS
  TABLE OF VARCHAR2(100);
type typ_progs
IS
  TABLE OF typ_program;
type typ_opers
IS
  TABLE OF VARCHAR2(10);
  c_operations_1 typ_opers := typ_opers('+', '-');
  c_operations_2 typ_opers := typ_opers('/', '*');
  c_operations_3 typ_opers := typ_opers('power', 'sqrt-n');
  c_operations_4 typ_opers := typ_opers('sin', 'cos', 'tan', 'sqrt');
  v_trail typ_program;
  v_program typ_program := typ_program();
  v_progs typ_progs     := typ_progs();
FUNCTION exist_operation(
    p_operation typ_opers,
    p_input VARCHAR2)
  RETURN BOOLEAN
IS
  result BOOLEAN;
BEGIN
  result := false;
  FOR i  IN p_operation.first .. p_operation.last
  LOOP
    IF (p_operation(i) = p_input) THEN
      result          := true;
      EXIT;
    END IF;
  END LOOP;
  RETURN result;
END;
FUNCTION calculator(
    p_head FLOAT,
    p_operation VARCHAR2,
    p_tail FLOAT)
  RETURN FLOAT
IS
  Result FLOAT;
BEGIN
  result := 0;
  CASE
  WHEN p_operation = '+' THEN
    result        := p_head + p_tail;
  WHEN p_operation = '-' THEN
    result        := p_head - p_tail;
  WHEN p_operation = '*' THEN
    result        := p_head * p_tail;
  WHEN p_operation = '/' THEN
    result        := p_head / p_tail;
  WHEN p_operation = 'power' THEN
    result        := power(p_head, p_tail);
  WHEN p_operation = 'sqrt' THEN
    result        := sqrt(p_tail);
  WHEN p_operation = 'sqrt-n' THEN
    result        := power(p_head, 1 / p_tail);
  WHEN p_operation = 'sin' THEN
    result        := sin(p_tail);
  WHEN p_operation = 'cos' THEN
    result        := cos(p_tail);
  WHEN p_operation = 'tan' THEN
    result        := cos(p_tail);
  END CASE;
  RETURN(Result);
END;
FUNCTION program(
    p_program typ_program)
  RETURN typ_program
IS
  v_program typ_program;
  v_head FLOAT;
  v_operation VARCHAR2(10);
  v_tail FLOAT;
BEGIN
  v_program := p_program;
  IF (v_program.exists(v_program.count - 1)) THEN
    IF (v_program(v_program.count      - 1) IN ('+', '-', '*', '/', 'power',
      'sqrt-n')) THEN
      v_head      := v_program(v_program.count - 2);
      v_operation := v_program(v_program.count - 1);
      v_tail      := v_program(v_program.count);
      v_program.trim(3);
      v_program.extend(1);
      v_program(v_program.count)          := calculator(v_head, v_operation, v_tail);
    elsif (v_program(v_program.count - 1) IN ('sin', 'cos', 'tan', 'sqrt'))
      THEN
      v_head      := 0;
      v_operation := v_program(v_program.count - 1);
      v_tail      := v_program(v_program.count);
      v_program.trim(2);
      v_program.extend(1);
      v_program(v_program.count) := calculator(v_head, v_operation, v_tail);
    END IF;
    IF (v_program.exists(v_program.count - 1)) THEN
      v_program := program(v_program);
    END IF;
  END IF;
  RETURN(v_program);
END;
FUNCTION run_program(
    p_trail typ_program)
  RETURN FLOAT
AS
  result FLOAT;
  v_trail typ_program;
  v_input VARCHAR2(300);
BEGIN
  result  := 0.0;
  v_trail := p_trail;
  v_progs.delete;
  v_program.delete;
  FOR i IN v_trail.first .. v_trail.last
  LOOP
    v_input := v_trail(i);
    CASE
    WHEN
      (
        v_input = '('
      )
      THEN
      v_progs.extend(1); --增加programs的元素program
      v_progs(v_progs.count) := v_program;
      v_program.delete; --删除v_program上所有元素
    WHEN
      (
        v_input = ')'
      )
      THEN
      v_program := program(v_program);
      v_progs(v_progs.count).extend(1);
      v_progs(v_progs.count)(v_progs(v_progs.count).count) := v_program(1);
      v_program                                            := v_progs(
      v_progs.count);
      v_progs.trim(1);
    WHEN
      (
        v_input = '='
      )
      THEN
      v_program := program(v_program);
    WHEN
      (
        exist_operation(c_operations_1, v_input)
      )
      THEN
      v_program := program(v_program);
      v_program.extend(1);
      v_program(v_program.count) := v_input;
    WHEN
      (
        exist_operation(c_operations_2, v_input)
      )
      THEN
      IF (v_program.exists(v_program.count                            - 1)) THEN
        IF (exist_operation(c_operations_2, v_program(v_program.count - 1)) OR
          exist_operation(c_operations_3, v_program(v_program.count   - 1)) OR
          exist_operation(c_operations_4, v_program(v_program.count   - 1)))
          THEN
          v_program := program(v_program);
        END IF;
      END IF;
      v_program.extend(1);
      v_program(v_program.count) := v_input;
    WHEN
      (
        exist_operation(c_operations_3, v_input) OR exist_operation(
        c_operations_4, v_input)
      )
      THEN
      IF (v_program.exists(v_program.count                            - 1)) THEN
        IF (exist_operation(c_operations_3, v_program(v_program.count - 1)) OR
          exist_operation(c_operations_4, v_program(v_program.count   - 1)))
          THEN
          v_program := program(v_program);
        END IF;
      END IF;
      v_program.extend(1);
      v_program(v_program.count) := v_input;
    ELSE
      /*case when else */
      v_program.extend(1);
      v_program(v_program.count) := v_input;
    END CASE;
  END LOOP;
  result := v_program(1);
  RETURN(result);
END;
FUNCTION desc_program(
    p_trail typ_program)
  RETURN VARCHAR2
AS
  result VARCHAR2(4000);
type t_boolean
IS
  TABLE OF BOOLEAN;
  v_trail typ_program;
  v_input            VARCHAR2(300);
  v_operation_change BOOLEAN;
  v_oper_changes t_boolean := t_boolean();
BEGIN
  result             := '';
  v_operation_change := false;
  v_trail            := p_trail;
  v_progs.delete;
  v_program.delete;
  FOR i IN v_trail.first .. v_trail.last
  LOOP
    v_input := v_trail(i);
    CASE
    WHEN
      (
        v_input = '('
      )
      THEN
      v_progs.extend(1); --增加programs的元素program
      v_progs(v_progs.count) := v_program;
      v_program.delete; --删除v_program上所有元素
      v_program.extend(1);
      v_program(v_program.count) := v_input;
      v_oper_changes.extend(1);
      v_oper_changes(v_oper_changes.count) := v_operation_change;
      v_operation_change                   := false;
    WHEN
      (
        v_input = ')'
      )
      THEN
      v_program.extend(1);
      v_program(v_program.count) := v_input;
      result                     := '';
      FOR j                      IN v_program.first .. v_program.last
      LOOP
        result := result || v_program(j);
      END LOOP;
      v_operation_change := v_oper_changes(v_oper_changes.count);
      v_oper_changes.trim(1);
      IF (v_operation_change) THEN
        v_operation_change := false;
        result             := '(1/' || result || ')';
      END IF;
      v_progs(v_progs.count).extend(1);
      v_progs(v_progs.count)(v_progs(v_progs.count).count) := result;
      v_program                                            := v_progs(
      v_progs.count);
      v_progs.trim(1);
    WHEN
      (
        v_input = 'sqrt-n'
      )
      THEN
      v_program.extend(1);
      v_input                    := '^';
      v_program(v_program.count) := v_input;
      v_operation_change         := true;
    ELSE
      /*case when else */
      IF (v_operation_change) THEN
        v_operation_change := false;
        v_program.extend(1);
        v_program(v_program.count) := '(1/' || v_input || ')';
      ELSE
        v_program.extend(1);
        IF (v_input = 'power' OR v_input = 'sqrt-n') THEN
          v_input  := '^';
        END IF;
        v_program(v_program.count) := v_input;
      END IF;
    END CASE;
  END LOOP;
  result := '';
  FOR j  IN v_program.first .. v_program.last
  LOOP
    result := result || v_program(j);
  END LOOP;
  RETURN(result);
END;
FUNCTION chinese_number(
    p_input FLOAT)
  RETURN VARCHAR2
AS
  /*
  created by wfg on 2012-7-27
  It is used to change Arabic numbers to Chinese big numbers.
  */
type typ_money
IS
  TABLE OF VARCHAR2(20);
  c_numbers typ_money := typ_money('零', '壹', '贰', '叁', '肆', '伍', '陆', '柒', '捌',
  '玖');
  c_unit typ_money := typ_money('分', '角', '圆', '拾', '佰', '仟', '万', '拾', '佰',
  '仟', '亿', '拾', '佰', '仟', '兆', '拾', '佰', '仟');
  v_array_money typ_money := typ_money();
  chinese_number   VARCHAR2(30);
  result           VARCHAR2(1000);
  v_number         INTEGER;
  v_number_element INTEGER;
  i                INT;
BEGIN
  IF (p_input >= power(10, 16)) THEN
    result    := '超出计算范围';
    RETURN result;
  END IF;
  v_number := ROUND(p_input * 100);
  i        := 1;
  v_array_money.extend(1);
  v_array_money(v_array_money.count) := '整';
  WHILE v_number                      > 0
  LOOP
    v_number_element    := mod(v_number, 10);
    IF (v_number_element = 0) THEN
      IF i              IN (3, 7, 11, 15) THEN
        chinese_number  := c_unit(i);
      ELSE
        chinese_number := c_numbers(v_number_element + 1);
      END IF;
    ELSE
      chinese_number := c_numbers(v_number_element + 1) || c_unit(i);
    END IF;
    CASE
    WHEN chinese_number                           = '零' THEN
      IF (v_array_money(v_array_money.count) NOT IN ('整', '零', '圆', '万', '亿',
        '兆')) THEN
        v_array_money.extend(1);
        v_array_money(v_array_money.count) := chinese_number;
      END IF;
    WHEN chinese_number LIKE '%亿' THEN
      IF (v_array_money(v_array_money.count) IN ('万')) THEN
        v_array_money(v_array_money.count)   := chinese_number;
      ELSE
        v_array_money.extend(1);
        v_array_money(v_array_money.count) := chinese_number;
      END IF;
    WHEN chinese_number LIKE '%兆' THEN
      IF (v_array_money(v_array_money.count) IN ('万', '亿')) THEN
        v_array_money(v_array_money.count)   := chinese_number;
      ELSE
        v_array_money.extend(1);
        v_array_money(v_array_money.count) := chinese_number;
      END IF;
    ELSE
      v_array_money.extend(1);
      v_array_money(v_array_money.count) := chinese_number;
    END CASE;
    v_number := floor(v_number / 10);
    i        := i              + 1;
  END LOOP;
  FOR i IN v_array_money.first .. v_array_money.last
  LOOP
    result := v_array_money(i) || result;
  END LOOP;
  RETURN result;
END;
BEGIN
  v_trail := typ_program('(', '2', '+', '3', ')', '*', '4', 'power', '(', '1',
  '+', '8', 'sqrt-n', '(', '2', '+', '2', ')', '+', '1', ')', '-', '10', '=');
  dbms_output.put('This programStack ' || (desc_program(v_trail)));
  dbms_output.put_line(' ' || run_program(v_trail));
  dbms_output.put_line('' || chinese_number(run_program(v_trail)));
END run_science_program_v2;
 

 

 

Version 1.0

 

create or replace procedure run_science_program as
  type typ_program is table of varchar2(100);
  type typ_progs is table of typ_program;
  type typ_opers is table of varchar2(10);
  c_operations_1 typ_opers := typ_opers('+', '-');
  c_operations_2 typ_opers := typ_opers('/', '*');
  c_operations_3 typ_opers := typ_opers('power', 'sqrt-n');
  c_operations_4 typ_opers := typ_opers('sin',
                                                  'cos',
                                                  'tan',
                                                  'sqrt');

  v_trail   typ_program;
  v_program typ_program := typ_program();
  v_progs   typ_progs := typ_progs();

  function exist_operation(p_operation typ_opers, p_input varchar2)
    return boolean is
    result boolean;
  begin
    result := false;
  
    for i in p_operation.first .. p_operation.last loop
      if (p_operation(i) = p_input) then
        result := true;
        exit;
      end if;
    end loop;
  
    return result;
  end;

  function calculator(p_head float, p_operation varchar2, p_tail float)
    return float is
    Result float;
  begin
    result := 0;
    case
      when p_operation = '+' then
        result := p_head + p_tail;
      when p_operation = '-' then
        result := p_head - p_tail;
      when p_operation = '*' then
        result := p_head * p_tail;
      when p_operation = '/' then
        result := p_head / p_tail;
      when p_operation = 'power' then
        result := power(p_head, p_tail);
      when p_operation = 'sqrt' then
        result := sqrt(p_tail);
      when p_operation = 'sqrt-n' then
        result := power(p_head, 1 / p_tail);
      when p_operation = 'sin' then
        result := sin(p_tail);
      when p_operation = 'cos' then
        result := cos(p_tail);
      when p_operation = 'tan' then
        result := cos(p_tail);
      
    end case;
  
    return(Result);
  end;

  function program(p_program typ_program) return typ_program is
    v_program   typ_program;
    v_head      float;
    v_operation varchar2(10);
    v_tail      float;
  begin
    v_program := p_program;
  
    if (v_program.exists(v_program.count - 1)) then
      if (v_program(v_program.count - 1) in
         ('+', '-', '*', '/', 'power', 'sqrt-n')) then
        v_head      := v_program(v_program.count - 2);
        v_operation := v_program(v_program.count - 1);
        v_tail      := v_program(v_program.count);
        v_program.trim(3);
        v_program.extend(1);
        v_program(v_program.count) := calculator(v_head,
                                                 v_operation,
                                                 v_tail);
      
      elsif (v_program(v_program.count - 1) in
            ('sin', 'cos', 'tan', 'sqrt')) then
        v_head      := 0;
        v_operation := v_program(v_program.count - 1);
        v_tail      := v_program(v_program.count);
        v_program.trim(2);
        v_program.extend(1);
        v_program(v_program.count) := calculator(v_head,
                                                 v_operation,
                                                 v_tail);
      
      end if;
    
      if (v_program.exists(v_program.count - 1)) then
        v_program := program(v_program);
      end if;
    
    end if;
  
    return(v_program);
  end;

  function run_program(p_trail typ_program) return float as
    result  float;
    v_trail typ_program;
    v_input varchar2(300);
  begin
    result  := 0.0;
    v_trail := p_trail;
    v_progs.delete;
    v_program.delete;
  
    for i in v_trail.first .. v_trail.last loop
      v_input := v_trail(i);
    
      case
        when (v_input = '(') then
          v_progs.extend(1); --增加programs的元素program
          v_progs(v_progs.count) := v_program;
        
          v_program.delete; --删除v_program上所有元素
      
        when (v_input = ')') then
        
          v_program := program(v_program);
        
          v_progs(v_progs.count).extend(1);
          v_progs(v_progs.count)(v_progs(v_progs.count).count) := v_program(1);
          v_program := v_progs(v_progs.count);
        
          v_progs.trim(1);
        
        when (v_input = '=') then
          v_program := program(v_program);
        
        when (exist_operation(c_operations_1, v_input)) then
        
          v_program := program(v_program);
        
          v_program.extend(1);
          v_program(v_program.count) := v_input;
        
        when (exist_operation(c_operations_2, v_input)) then
          if (v_program.exists(v_program.count - 1)) then
            if (exist_operation(c_operations_2,
                                v_program(v_program.count - 1)) or
               exist_operation(c_operations_3,
                                v_program(v_program.count - 1)) or
               exist_operation(c_operations_4,
                                v_program(v_program.count - 1))) then
              v_program := program(v_program);
            end if;
          end if;
          v_program.extend(1);
          v_program(v_program.count) := v_input;
        
        when (exist_operation(c_operations_3, v_input) or
             exist_operation(c_operations_4, v_input)) then
          if (v_program.exists(v_program.count - 1)) then
            if (exist_operation(c_operations_3,
                                v_program(v_program.count - 1)) or
               exist_operation(c_operations_4,
                                v_program(v_program.count - 1))) then
              v_program := program(v_program);
            end if;
          end if;
          v_program.extend(1);
          v_program(v_program.count) := v_input;
        
        else
          /*case when else */
          v_program.extend(1);
          v_program(v_program.count) := v_input;
        
      end case;
    
    end loop;
  
    result := v_program(1);
  
    return(result);
  end;

  function desc_program(p_trail typ_program) return varchar2 as
    result varchar2(4000);
    type t_boolean is table of boolean;
    v_trail            typ_program;
    v_input            varchar2(300);
    v_operation_change BOOLEAN;
    v_oper_changes     t_boolean := t_boolean();
  begin
    result             := '';
    v_operation_change := false;
    v_trail            := p_trail;
    v_progs.delete;
    v_program.delete;
  
    for i in v_trail.first .. v_trail.last loop
      v_input := v_trail(i);
    
      case
        when (v_input = '(') then
        
          v_progs.extend(1); --增加programs的元素program
          v_progs(v_progs.count) := v_program;
          v_program.delete; --删除v_program上所有元素
        
          v_program.extend(1);
          v_program(v_program.count) := v_input;
        
          v_oper_changes.extend(1);
          v_oper_changes(v_oper_changes.count) := v_operation_change;
          v_operation_change := false;
        
        when (v_input = ')') then
          v_program.extend(1);
          v_program(v_program.count) := v_input;
        
          v_operation_change := v_oper_changes(v_oper_changes.count);
          v_oper_changes.trim(1);
          if (v_operation_change) then
            v_operation_change := false;
            v_program.extend(1);
            v_program(v_program.count) := ')';
          end if;
        
          for j in v_program.first .. v_program.last loop
            result := result || v_program(j);
          end loop;
          v_progs(v_progs.count).extend(1);
          v_progs(v_progs.count)(v_progs(v_progs.count).count) := result;
        
          v_program := v_progs(v_progs.count);
        
          v_progs.trim(1);
          result := '';
        
        when (exist_operation(c_operations_3, v_input)) then
        
          v_program(v_program.count) := v_input || '(' ||
                                        v_program(v_program.count) || ',';
          v_operation_change := true;
        
        else
          /*case when else */
          if (v_operation_change) then
            v_operation_change := false;
            v_program.extend(1);
            v_program(v_program.count) := v_input;
            v_program.extend(1);
            v_program(v_program.count) := ')';
          
          else
          
            v_program.extend(1);
            v_program(v_program.count) := v_input;
          end if;
      end case;
    
    end loop;
  
    for j in v_program.first .. v_program.last loop
      result := result || v_program(j);
    end loop;
  
    return(result);
  end;

begin
  /*
  v_trail := typ_program('5',
                         '+',
                         '9',
                         'power',
                         '(',
                         '2',
                         '*',
                         '2',
                         ')',
                         '+',
                         '2',
                         '*',
                         '(',
                         '30',
                         '+',
                         '10',
                         ')',
                         '-',
                         '10',
                         '=');
  */
  v_trail := typ_program('(',
                         '2',
                         '+',
                         '3',
                         ')',
                         '*',
                         '4',
                         'power',
                         '(',
                         '1',
                         '+',
                         'sqrt',
                         '(',
                         '2',
                         '+',
                         '2',
                         ')',
                         '+',
                         '1',
                         ')',
                         '-',
                         '10',
                         '=');

  dbms_output.put('This programStack ' || desc_program(v_trail));

  dbms_output.put_line(' ' || run_program(v_trail));

end run_science_program;