PostgreSQL 16 新特性之正态分布随机数函数的示例
不剪发的Tony老师 人气:0random() 函数可以用于生成一个大于等于 0 小于等于 1 的随机数,生成的数据遵循平均分布。不过在实际环境中,更多的数据则是遵循正态分布。PostgreSQL 提供了一个扩展模块 tablefunc,可以用于生成遵循正态分布的随机数;或者我们也可以创建存储函数来模拟正态分布的随机数。
考虑到它的实用性,PostgreSQL 16 新增了一个内置的 random_normal() 函数,用于生成这种随机数。我们使用该函数生成 10 个随机数:
select random_normal() as v from generate_series(1, 10); v | -------------------+ 1.9147182783615317| -1.7265731892046994| -0.9601043210986459| -1.481551351102244| -1.3763031483133177| 0.11872324455736474| 0.9016843380853512| 0.1288806844184827| -1.6392171916791691| 0.33770959079074697|
默认参数调用时,random_normal() 函数生成的随机数遵循标准正态分布(均值为 0,标准差为 1)。
以下示例生成的随机数遵循均值为 1、标准差为 5 的正态分布:
select random_normal(1, 5) as v from generate_series(1, 10); v | -------------------+ -0.4529440542028027| 5.442251124798599| 6.307851828542196| 4.122825670258253| -2.186242122101672| 4.767936509571358| 5.172144288566877| -3.761475521327373| -2.6431751259304193| 0.19249449162595722|
接下来我们验证一下该函数生成的数据是否遵循正态分布。
SELECT round(random_normal(1, 0.5)::numeric, 1) AS v, count(*), repeat('#', (count(*) / 100)::integer) FROM generate_series(1, 100000) GROUP BY v ORDER BY v; v |count|repeat | ----+-----+-------------------------------------------------------------------------------+ -1.2| 1| | -1.1| 1| | -1.0| 3| | -0.9| 9| | -0.8| 17| | -0.7| 21| | -0.6| 55| | -0.5| 98| | -0.4| 132|# | -0.3| 248|## | -0.2| 521|##### | -0.1| 728|####### | 0.0| 1090|########## | 0.1| 1586|############### | 0.2| 2203|###################### | 0.3| 2975|############################# | 0.4| 3878|###################################### | 0.5| 4840|################################################ | 0.6| 5778|######################################################### | 0.7| 6670|################################################################## | 0.8| 7299|######################################################################## | 0.9| 7720|############################################################################# | 1.0| 7960|###############################################################################| 1.1| 7794|############################################################################# | 1.2| 7271|######################################################################## | 1.3| 6745|################################################################### | 1.4| 5796|######################################################### | 1.5| 4796|############################################### | 1.6| 3904|####################################### | 1.7| 3034|############################## | 1.8| 2300|####################### | 1.9| 1567|############### | 2.0| 1175|########### | 2.1| 710|####### | 2.2| 454|#### | 2.3| 267|## | 2.4| 164|# | 2.5| 94| | 2.6| 56| | 2.7| 23| | 2.8| 7| | 2.9| 8| | 3.0| 2| |
从上面的图形可以看出,函数返回的结果是一个正态分布。我们还可以进一步通过均值和标准差进行验证:
WITH RECURSIVE d(n, v) AS ( SELECT 1 AS n, random_normal(1, 0.5) AS v UNION ALL SELECT n+1, random_normal(1, 0.5) FROM d WHERE n<100000 ) SELECT count(*), avg(v), stddev(v) FROM d; count |avg |stddev | ------+------------------+-------------------+ 100000|1.0009116232651825|0.49890904328727353|
加载全部内容