首頁
編程語言
C語言|JAVA編程
Python編程
網頁編程
ASP編程|PHP編程
JSP編程
數據庫
MYSQL數據庫|SqlServer數據庫
Oracle數據庫|DB2數據庫
您现在的位置: 程式碼之家 >> 數據庫知識 >  >> Oracle 資料庫 >> Oracle 資料庫基礎

PL/SQL 實作高效能隨機數產生器套件

     編輯:Oracle 資料庫基礎

設計目標

Oracle 內建無隨機數函數。實作一個可設定範圍、種子、整數/浮點模式的 PL/SQL Package,採線性同餘法 (LCG) 演算法。

完整 Package 程式碼

CREATE OR REPLACE PACKAGE pk_rand IS
    PROCEDURE set_range(p_lower IN NUMBER, p_upper IN NUMBER, p_integer IN VARCHAR2 DEFAULT 'Y');
    PROCEDURE set_seed(p_seed IN NUMBER);
    PROCEDURE rand(p_result OUT NUMBER);
    FUNCTION f_rand RETURN NUMBER;
    PRAGMA RESTRICT_REFERENCES(f_rand, WNDS);
END;
/

CREATE OR REPLACE PACKAGE BODY pk_rand IS
    v_range_lower NUMBER := 0;
    v_range_upper NUMBER := 1;
    v_lastval     NUMBER;
    v_integer     BOOLEAN := FALSE;

    CURSOR c_seed IS SELECT TO_CHAR(SYSDATE, 'SSSSSDDDHHSSSSS') FROM dual;

    PROCEDURE set_seed(p_seed IN NUMBER) IS
    BEGIN v_lastval := p_seed; END;

    PROCEDURE set_range(p_lower IN NUMBER, p_upper IN NUMBER, p_integer IN VARCHAR2 DEFAULT 'Y') IS
    BEGIN
        v_range_lower := p_lower;
        v_range_upper := p_upper;
        v_integer := (p_integer = 'Y');
    END;

    PROCEDURE rand(p_result OUT NUMBER) IS
    BEGIN p_result := f_rand; END;

    FUNCTION f_rand RETURN NUMBER IS
        a CONSTANT NUMBER := 25214903917;
        c CONSTANT NUMBER := 11;
        m CONSTANT NUMBER := POWER(2,48);
        v_rand NUMBER;
        v_result NUMBER;
    BEGIN
        v_rand := MOD(a * v_lastval + c, m);
        v_lastval := v_rand;
        v_rand := v_rand / m;  -- 0~1 之間

        IF v_integer THEN
            v_result := TRUNC(v_rand * ((v_range_upper + 1) - v_range_lower) + v_range_lower);
        ELSE
            v_result := v_rand * (v_range_upper - v_range_lower) + v_range_lower;
        END IF;
        RETURN v_result;
    END;

BEGIN
    OPEN c_seed;
    FETCH c_seed INTO v_lastval;
    CLOSE c_seed;
END;
/

使用範例

-- 設定產生 1~100 整數
BEGIN pk_rand.set_range(1, 100, 'Y'); END;
/

-- 取單一隨機數
DECLARE v_num NUMBER; BEGIN pk_rand.rand(v_num); DBMS_OUTPUT.PUT_LINE(v_num); END;
/

-- 直接呼叫函數
SELECT pk_rand.f_rand FROM dual;

演算法說明

  • 線性同餘法:X_{n+1} = (a * X_n + c) mod m
  • 常數採用 Java java.util.Random 相同參數,週期 2^48
  • 初始種子取系統時間細碼,確保每次啟動序列不同
  1. 上一篇文章:
  2. 下一篇文章:
Copyright © 程式碼之家 All Rights Reserved