Spracherkennung für: .out vermutete Sprache: Unknown {[0] [0] [0]} [Methode: Schwerpunktbildung, einfache Gewichte, sechs Dimensionen]
--
-- RANDOM
-- Test random() and allies
--
-- Tests in this file may have a small probability of failure,
-- since we are dealing with randomness. Try to keep the failure
-- risk for any one test case under
1e-
9.
--
-- There should be no duplicates in
1000 random() values.
-- (Assuming
52 random bits in the float8 results, we could
-- take as many as
3000 values and still have less than
1e-
9 chance
-- of failure, per
https://en.wikipedia.org/wiki/Birthday_problem)
SELECT r, count(*)
FROM (SELECT random() r FROM generate_series(
1,
1000)) ss
GROUP BY r HAVING count(*) >
1;
r | count
---+-------
(
0 rows)
-- The range should be [
0,
1). We can expect that at least one out of
2000
-- random values is in the lowest or highest
1% of the range with failure
-- probability less than about
1e-
9.
SELECT count(*) FILTER (WHERE r <
0 OR r >=
1) AS out_of_range,
(count(*) FILTER (WHERE r <
0.
01)) >
0 AS has_small,
(count(*) FILTER (WHERE r >
0.
99)) >
0 AS has_large
FROM (SELECT random() r FROM generate_series(
1,
2000)) ss;
out_of_range | has_small | has_large
--------------+-----------+-----------
0 | t | t
(
1 row)
-- Check for uniform distribution using the Kolmogorov-Smirnov test.
CREATE FUNCTION ks_test_uniform_random()
RETURNS boolean AS
$$
DECLARE
n int :=
1000; -- Number of samples
c float8 :=
1.
94947; -- Critical value for
99.
9% confidence
ok boolean;
BEGIN
ok := (
WITH samples AS (
SELECT random() r FROM generate_series(
1, n) ORDER BY
1
), indexed_samples AS (
SELECT (row_number() OVER())-
1.
0 i, r FROM samples
)
SELECT max(abs(i/n-r)) < c / sqrt(n) FROM indexed_samples
);
RETURN ok;
END
$$
LANGUAGE plpgsql;
-- As written, ks_test_uniform_random() returns true about
99.
9%
-- of the time. To get down to a roughly
1e-
9 test failure rate,
-- just run it
3 times and accept if any one of them passes.
SELECT ks_test_uniform_random() OR
ks_test_uniform_random() OR
ks_test_uniform_random() AS uniform;
uniform
---------
t
(
1 row)
-- now test random_normal()
-- As above, there should be no duplicates in
1000 random_normal() values.
SELECT r, count(*)
FROM (SELECT random_normal() r FROM generate_series(
1,
1000)) ss
GROUP BY r HAVING count(*) >
1;
r | count
---+-------
(
0 rows)
-- ... unless we force the range (standard deviation) to zero.
-- This is a good place to check that the mean input does something, too.
SELECT r, count(*)
FROM (SELECT random_normal(
10,
0) r FROM generate_series(
1,
100)) ss
GROUP BY r;
r | count
----+-------
10 |
100
(
1 row)
SELECT r, count(*)
FROM (SELECT random_normal(-
10,
0) r FROM generate_series(
1,
100)) ss
GROUP BY r;
r | count
-----+-------
-
10 |
100
(
1 row)
-- Check standard normal distribution using the Kolmogorov-Smirnov test.
CREATE FUNCTION ks_test_normal_random()
RETURNS boolean AS
$$
DECLARE
n int :=
1000; -- Number of samples
c float8 :=
1.
94947; -- Critical value for
99.
9% confidence
ok boolean;
BEGIN
ok := (
WITH samples AS (
SELECT random_normal() r FROM generate_series(
1, n) ORDER BY
1
), indexed_samples AS (
SELECT (row_number() OVER())-
1.
0 i, r FROM samples
)
SELECT max(abs((
1+erf(r/sqrt(
2)))/
2 - i/n)) < c / sqrt(n)
FROM indexed_samples
);
RETURN ok;
END
$$
LANGUAGE plpgsql;
-- As above, ks_test_normal_random() returns true about
99.
9%
-- of the time, so try it
3 times and accept if any test passes.
SELECT ks_test_normal_random() OR
ks_test_normal_random() OR
ks_test_normal_random() AS standard_normal;
standard_normal
-----------------
t
(
1 row)
-- Test random(min, max)
-- invalid range bounds
SELECT random(
1,
0);
ERROR: lower bound must be less than or equal to upper bound
SELECT random(
1000000000001,
1000000000000);
ERROR: lower bound must be less than or equal to upper bound
SELECT random(-
2.
0, -
3.
0);
ERROR: lower bound must be less than or equal to upper bound
SELECT random('NaN'::numeric,
10);
ERROR: lower bound cannot be NaN
SELECT random('-Inf'::numeric,
0);
ERROR: lower bound cannot be infinity
SELECT random(
0, 'NaN'::numeric);
ERROR: upper bound cannot be NaN
SELECT random(
0, 'Inf'::numeric);
ERROR: upper bound cannot be infinity
-- empty range is OK
SELECT random(
101,
101);
random
--------
101
(
1 row)
SELECT random(
1000000000001,
1000000000001);
random
---------------
1000000000001
(
1 row)
SELECT random(
3.
14,
3.
14);
random
--------
3.
14
(
1 row)
-- There should be no triple duplicates in
1000 full-range
32-bit random()
-- values. (Each of the C(
1000,
3) choices of triplets from the
1000 values
-- has a probability of
1/(
2^
32)^
2 of being a triple duplicate, so the
-- average number of triple duplicates is
1000 *
999 *
998 /
6 /
2^
64, which
-- is roughly
9e-
12.)
SELECT r, count(*)
FROM (SELECT random(-
2147483648,
2147483647) r
FROM generate_series(
1,
1000)) ss
GROUP BY r HAVING count(*) >
2;
r | count
---+-------
(
0 rows)
-- There should be no duplicates in
1000 full-range
64-bit random() values.
SELECT r, count(*)
FROM (SELECT random_normal(-
9223372036854775808,
9223372036854775807) r
FROM generate_series(
1,
1000)) ss
GROUP BY r HAVING count(*) >
1;
r | count
---+-------
(
0 rows)
-- There should be no duplicates in
1000 15-digit random() numeric values.
SELECT r, count(*)
FROM (SELECT random_normal(
0,
1 -
1e-
15) r
FROM generate_series(
1,
1000)) ss
GROUP BY r HAVING count(*) >
1;
r | count
---+-------
(
0 rows)
-- Expect at least one out of
2000 random values to be in the lowest and
-- highest
1% of the range.
SELECT (count(*) FILTER (WHERE r < -
2104533975)) >
0 AS has_small,
(count(*) FILTER (WHERE r >
2104533974)) >
0 AS has_large
FROM (SELECT random(-
2147483648,
2147483647) r FROM generate_series(
1,
2000)) ss;
has_small | has_large
-----------+-----------
t | t
(
1 row)
SELECT count(*) FILTER (WHERE r < -
1500000000 OR r >
1500000000) AS out_of_range,
(count(*) FILTER (WHERE r < -
1470000000)) >
0 AS has_small,
(count(*) FILTER (WHERE r >
1470000000)) >
0 AS has_large
FROM (SELECT random(-
1500000000,
1500000000) r FROM generate_series(
1,
2000)) ss;
out_of_range | has_small | has_large
--------------+-----------+-----------
0 | t | t
(
1 row)
SELECT (count(*) FILTER (WHERE r < -
9038904596117680292)) >
0 AS has_small,
(count(*) FILTER (WHERE r >
9038904596117680291)) >
0 AS has_large
FROM (SELECT random(-
9223372036854775808,
9223372036854775807) r
FROM generate_series(
1,
2000)) ss;
has_small | has_large
-----------+-----------
t | t
(
1 row)
SELECT count(*) FILTER (WHERE r < -
1500000000000000 OR r >
1500000000000000) AS out_of_range,
(count(*) FILTER (WHERE r < -
1470000000000000)) >
0 AS has_small,
(count(*) FILTER (WHERE r >
1470000000000000)) >
0 AS has_large
FROM (SELECT random(-
1500000000000000,
1500000000000000) r
FROM generate_series(
1,
2000)) ss;
out_of_range | has_small | has_large
--------------+-----------+-----------
0 | t | t
(
1 row)
SELECT count(*) FILTER (WHERE r < -
1.
5 OR r >
1.
5) AS out_of_range,
(count(*) FILTER (WHERE r < -
1.
47)) >
0 AS has_small,
(count(*) FILTER (WHERE r >
1.
47)) >
0 AS has_large
FROM (SELECT random(-
1.
500000000000000,
1.
500000000000000) r
FROM generate_series(
1,
2000)) ss;
out_of_range | has_small | has_large
--------------+-----------+-----------
0 | t | t
(
1 row)
-- Every possible value should occur at least once in
2500 random() values
-- chosen from a range with
100 distinct values.
SELECT min(r), max(r), count(r) FROM (
SELECT DISTINCT random(-
50,
49) r FROM generate_series(
1,
2500));
min | max | count
-----+-----+-------
-
50 |
49 |
100
(
1 row)
SELECT min(r), max(r), count(r) FROM (
SELECT DISTINCT random(
123000000000,
123000000099) r
FROM generate_series(
1,
2500));
min | max | count
--------------+--------------+-------
123000000000 |
123000000099 |
100
(
1 row)
SELECT min(r), max(r), count(r) FROM (
SELECT DISTINCT random(-
0.
5,
0.
49) r FROM generate_series(
1,
2500));
min | max | count
-------+------+-------
-
0.
50 |
0.
49 |
100
(
1 row)
-- Check for uniform distribution using the Kolmogorov-Smirnov test.
CREATE FUNCTION ks_test_uniform_random_int_in_range()
RETURNS boolean AS
$$
DECLARE
n int :=
1000; -- Number of samples
c float8 :=
1.
94947; -- Critical value for
99.
9% confidence
ok boolean;
BEGIN
ok := (
WITH samples AS (
SELECT random(
0,
999999) /
1000000.
0 r FROM generate_series(
1, n) ORDER BY
1
), indexed_samples AS (
SELECT (row_number() OVER())-
1.
0 i, r FROM samples
)
SELECT max(abs(i/n-r)) < c / sqrt(n) FROM indexed_samples
);
RETURN ok;
END
$$
LANGUAGE plpgsql;
SELECT ks_test_uniform_random_int_in_range() OR
ks_test_uniform_random_int_in_range() OR
ks_test_uniform_random_int_in_range() AS uniform_int;
uniform_int
-------------
t
(
1 row)
CREATE FUNCTION ks_test_uniform_random_bigint_in_range()
RETURNS boolean AS
$$
DECLARE
n int :=
1000; -- Number of samples
c float8 :=
1.
94947; -- Critical value for
99.
9% confidence
ok boolean;
BEGIN
ok := (
WITH samples AS (
SELECT random(
0,
999999999999) /
1000000000000.
0 r FROM generate_series(
1, n) ORDER BY
1
), indexed_samples AS (
SELECT (row_number() OVER())-
1.
0 i, r FROM samples
)
SELECT max(abs(i/n-r)) < c / sqrt(n) FROM indexed_samples
);
RETURN ok;
END
$$
LANGUAGE plpgsql;
SELECT ks_test_uniform_random_bigint_in_range() OR
ks_test_uniform_random_bigint_in_range() OR
ks_test_uniform_random_bigint_in_range() AS uniform_bigint;
uniform_bigint
----------------
t
(
1 row)
CREATE FUNCTION ks_test_uniform_random_numeric_in_range()
RETURNS boolean AS
$$
DECLARE
n int :=
1000; -- Number of samples
c float8 :=
1.
94947; -- Critical value for
99.
9% confidence
ok boolean;
BEGIN
ok := (
WITH samples AS (
SELECT random(
0,
0.
999999) r FROM generate_series(
1, n) ORDER BY
1
), indexed_samples AS (
SELECT (row_number() OVER())-
1.
0 i, r FROM samples
)
SELECT max(abs(i/n-r)) < c / sqrt(n) FROM indexed_samples
);
RETURN ok;
END
$$
LANGUAGE plpgsql;
SELECT ks_test_uniform_random_numeric_in_range() OR
ks_test_uniform_random_numeric_in_range() OR
ks_test_uniform_random_numeric_in_range() AS uniform_numeric;
uniform_numeric
-----------------
t
(
1 row)
-- setseed() should produce a reproducible series of random() values.
SELECT setseed(
0.
5);
setseed
---------
(
1 row)
SELECT random() FROM generate_series(
1,
10);
random
---------------------
0.
9851677175347999
0.
825301858027981
0.
12974610012450416
0.
16356291958601088
0.
6476186144084
0.
8822771983038762
0.
1404566845227775
0.
15619865764623442
0.
5145227426983392
0.
7712969548127826
(
10 rows)
-- Likewise for random_normal(); however, since its implementation relies
-- on libm functions that have different roundoff behaviors on different
-- machines, we have to round off the results a bit to get consistent output.
SET extra_float_digits = -
1;
SELECT random_normal() FROM generate_series(
1,
10);
random_normal
-------------------
0.
20853464493838
0.
26453024054096
-
0.
60675246790043
0.
82579942785265
1.
7011161173536
-
0.
22344546371619
0.
249712419191
-
1.
2494722990669
0.
12562715204368
0.
47539161454401
(
10 rows)
SELECT random_normal(mean =>
1, stddev =>
0.
1) r FROM generate_series(
1,
10);
r
------------------
1.
0060597281173
1.
09685453015
1.
0286920613201
0.
90947567671234
0.
98372476313426
0.
93934454957762
1.
1871350020636
0.
96225768429293
0.
91444120680041
0.
96403105557543
(
10 rows)
-- Reproducible random(min, max) values.
SELECT random(
1,
6) FROM generate_series(
1,
10);
random
--------
5
4
5
1
6
1
1
3
6
5
(
10 rows)
SELECT random(-
2147483648,
2147483647) FROM generate_series(
1,
10);
random
-------------
-
84380014
1287883594
-
1927252904
13516867
-
1902961616
-
1824286201
-
871264469
-
1225880415
229836730
-
116039023
(
10 rows)
SELECT random(-
9223372036854775808,
9223372036854775807) FROM generate_series(
1,
10);
random
----------------------
-
6205280962992680052
-
3583519428011353337
511801786318122700
4672737727839409655
-
6674868801536280768
-
7816052100626646489
-
4340613370136007199
-
5873174504107419786
-
2249910101649817824
-
4493828993910792325
(
10 rows)
SELECT random(-
1e30,
1e30) FROM generate_series(
1,
10);
random
---------------------------------
-
732116469803315942112255539315
794641423514877972798449289857
-
576932746026123093304638334719
420625067723533225139761854757
-
339227806779403187811001078919
-
77667951539418104959241732636
239810941795708162629328071599
820784371155896967052141946697
-
377084684544126871150439048352
-
979773225250716295007225086726
(
10 rows)
SELECT random(-
0.
4,
0.
4) FROM generate_series(
1,
10);
random
--------
0.
1
0.
0
0.
4
-
0.
2
0.
1
0.
2
0.
3
0.
0
-
0.
2
0.
2
(
10 rows)
SELECT random(
0,
1 -
1e-
30) FROM generate_series(
1,
10);
random
----------------------------------
0.
676442053784930109917469287265
0.
221310454098356723569995592911
0.
060101338174419259555193956224
0.
509960354695248239243002172364
0.
248680813394555793693952296993
0.
353262552880008646603494668901
0.
760692600450339509843044233719
0.
554987655310094483449494782510
0.
330890988458592995280347745733
0.
665435298280470361228607881507
(
10 rows)
SELECT n, random(
0, trim_scale(abs(
1 -
10.
0^(-n)))) FROM generate_series(-
20,
20) n;
n | random
-----+------------------------
-
20 |
94174615760837282445
-
19 |
6692559888531296894
-
18 |
801114552709125931
-
17 |
44091460959939971
-
16 |
2956109297383113
-
15 |
783332278684523
-
14 |
81534303241440
-
13 |
2892623140500
-
12 |
269397605141
-
11 |
13027512296
-
10 |
9178377775
-
9 |
323534150
-
8 |
91897803
-
7 |
6091383
-
6 |
13174
-
5 |
92714
-
4 |
8079
-
3 |
429
-
2 |
30
-
1 |
3
0 |
0
1 |
0.
1
2 |
0.
69
3 |
0.
492
4 |
0.
7380
5 |
0.
77078
6 |
0.
738142
7 |
0.
1808815
8 |
0.
14908933
9 |
0.
222654042
10 |
0.
2281295170
11 |
0.
73655782966
12 |
0.
056357256884
13 |
0.
8998407524375
14 |
0.
28198400530206
15 |
0.
713478222805230
16 |
0.
0415046850936909
17 |
0.
45946350291315119
18 |
0.
310966980367873753
19 |
0.
4967623661709676512
20 |
0.
60795101234744211935
(
41 rows)