2014-03-13 19 views
1

下面的pl/sql程序在執行時產生一個錯誤總和:= temp * sum;遇到符號;期待時(請說明我的錯誤。pl/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; 
/

回答

3

總額在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; 
/
+0

非常感謝。我一直在苦苦掙扎。 – rippy

5

也許得不到答案更改變量名你的問題,但沒有必要對PL/SQL這裏:

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

其中5是你的電話號碼(5!

添加。如果您希望在PL/SQL中使用更快的操作,則使用pls_integer而不是number

UPDATE

所以根據意見,我測試感到了自由:

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秒,所以程序只會更快一點,甚至沒有雙贏的表現。如果您在查詢中使用該函數,您將獲得完全相反的效果,因此這是公平交易。

+0

感謝您分享這些有用的信息:) – rippy

+0

運行sql來計算可以在純PL/SQL中計算出來的東西,我強烈懷疑它的效率要低得多。經驗法則「如果可以使用SQL,則不使用PL/SQL」不適用於此處。 –

+0

@JeffreyKemp,我不會那麼肯定,請證明你的猜測,只有在那之後我纔會明白「-1」。 – smnbbrv

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; 
+0

除了代碼之外,一些解釋會使這個答案對未來的讀者更有用。 –

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×10^456568個

+0

這是不可讀的。使用通過單擊幫助解釋的代碼格式。另外,通過解釋你正在闡述@ smnbbrv的答案,爲你的答案提供背景。你的回答與這個問題無關,而且你不清楚你喜歡什麼「甚至更好」 –