Oracle 內建無隨機數函數。實作一個可設定範圍、種子、整數/浮點模式的 PL/SQL Package,採線性同餘法 (LCG) 演算法。
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 mjava.util.Random 相同參數,週期 2^48