pl / sql中的数字的阶乘

时间:2014-03-13 08:07:54

标签: oracle plsql syntax-error

以下pl / sql程序在行上执行生成错误:sum:= temp * sum;遇到符号;期待时(。请解释我的错误。

declare
  n number;
  temp number;
  sum number := 1;
begin
  n := &n;
  temp := n;
  while temp>0 loop
    sum := temp*sum;
    temp := temp-1;
  end loop;
  dbms_output.put_line('Factorial of '||n||' is '||sum);
end;
/

5 个答案:

答案 0 :(得分:5)

也许不是你问题的答案,但这里不需要PL / SQL:

select round(exp(sum(ln(level))))
from dual
connect by level <= 5;

其中5是您的号码(5!)。

此外,如果您希望在PL / SQL中更快地运行pls_integer而不是number

<强>更新

所以根据评论,我可以随意测试:

create or replace package test_ is

  function by_query(num number) return number deterministic;

  function by_plsql(num number) return number deterministic;

end test_;

/

create or replace package body test_ is

  function by_query(num number) return number deterministic
    is
      res    number;
  begin
    select round(exp(sum(ln(level))))
    into res
    from dual
    connect by level <= num;

    return res;
  end;

  function by_plsql(num number) return number deterministic
    is
      n number := 0;
  begin
    for i in 1..num loop
      n := n + ln(i);
    end loop;

    return round(exp(n));
  end;

end test_;

因此有两个功能具有不同的内容。测试查询:

declare
  dummy   number;
begin
  for i in 1..10000 loop
    dummy := test_.by_query(5);
  end loop;
end;

0.094秒

declare
  dummy   number;
begin
  for i in 1..10000 loop
    dummy := test_.by_plsql(5);
  end loop;
end;

0.094秒

你会说我是骗子并且使用deterministic关键字,但这里显而易见并且需要逻辑。如果我删除它,相同的脚本工作1.7秒对1.3秒,所以程序只是更快一点,性能甚至没有双赢。如果在查询中使用该函数,则会产生完全相反的效果,因此这是一种公平交易。

答案 1 :(得分:3)

Sum是sql中的保留字。更改变量名称,如

declare
  n number;
  temp number;
  sum_ number := 1;
begin
  n := &n;
  temp := n;
  while temp>0 loop
    sum_ := temp*sum_;
    temp := temp-1;
  end loop;
  dbms_output.put_line('Factorial of '||n||' is '||sum_);
end;
/

答案 2 :(得分:0)

declare
    n number;
    i number;
    sum_of_log_10s number;
    exponent number;
    base number;

begin
    n := &n;

    i := 1;
    sum_of_log_10s := 0;

    while i <= n loop
        -- do stuff
        sum_of_log_10s := sum_of_log_10s + log(10,i);
        i := i + 1;
    end loop;

    dbms_output.put_line('sum of logs = '||sum_of_log_10s);

    exponent := floor(sum_of_log_10s);

    base := power(10,sum_of_log_10s - exponent);

    dbms_output.put_line(n||'! = '||base||' x 10^'||exponent);

end;

答案 3 :(得分:0)

我想出了这个代码,我比@ smnbbrv的回答更好。这是检查机器速度的好方法。自从我的Atari 800以来,我一直在使用这种变体

ALTER SESSION FORCE PARALLEL DDL PARALLEL 16; 
ALTER SESSION FORCE PARALLEL DML PARALLEL 16; 
ALTER SESSION FORCE PARALLEL QUERY PARALLEL 16; 

with t as (
    select /*+materialize*/
        rownum i 
    from dual connect by rownum < 100000 -- put number to calculate n! here
)
,t1 as (
    select /*+parallel(t,16)*/ /*+materialize*/
        sum(log(10,i)) logsum
    from t
    )
select 
    trunc(power(10,(mod(logsum,1))),3) ||' x 10^'||trim(to_char(floor(logsum),'999,999,999,999')) factorial
--  logsum
from t1
;

- 返回2.824 x 10 ^ 456,568

答案 4 :(得分:0)

这是在运行时查找数字阶乘的简单代码...

declare
 -- it gives the final answer after computation 
        fac number :=1; 
        -- given number n 
        -- taking input from user 
        n number := &1; 

        -- start block 
        begin   

        -- start while loop  
        while n > 0 loop 

        -- multiple with n and decrease n's value 
        fac:=n*fac;    

        --dbms_output.put(n||'*'); 
        n:=n-1;    
        end loop;    
        -- end loop 

        -- print result of fac 
        dbms_output.put_line(fac); 

        -- end the begin block 
        end;