{"id":319597,"date":"2021-03-15T15:00:50","date_gmt":"2021-03-15T15:00:50","guid":{"rendered":"http:\/\/savepearlharbor.com\/?p=319597"},"modified":"-0001-11-30T00:00:00","modified_gmt":"-0001-11-29T21:00:00","slug":"","status":"publish","type":"post","link":"https:\/\/savepearlharbor.com\/?p=319597","title":{"rendered":"\u0421\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0441\u0442\u0438 \u043d\u0435 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b"},"content":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/55e\/cc7\/a7b\/55ecc7a7b69cc959969b8f667a328d4c.jpg\" width=\"700\" height=\"356\"><figcaption><\/figcaption><\/figure>\n<p>\u041c\u043e\u0436\u043d\u043e \u043b\u0438 \u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0431\u0443\u0434\u0443\u0449\u0435\u0435 \u0445\u043e\u0442\u044c \u043d\u0430 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0432\u043f\u0435\u0440\u0435\u0434? \u0418\u043d\u043e\u0433\u0434\u0430 &#8212; \u0432\u043f\u043e\u043b\u043d\u0435, \u043d\u0430\u0434\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u043d\u043e\u0433\u043e \u0432\u0435\u0437\u0435\u043d\u0438\u044f&#8230; \u0438\u043b\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u043d\u0438\u0439.<\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u0440\u043e\u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0435\u043c \u0441\u0435\u0430\u043d\u0441 \u0447\u0435\u0440\u043d\u043e\u0439 \u043c\u0430\u0433\u0438\u0438 \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0440\u0430\u0437\u043e\u0431\u043b\u0430\u0447\u0435\u043d\u0438\u0435\u043c, \u0438\u043b\u0438 <strong><em>\u00ab\u042f \u0443\u0433\u0430\u0434\u0430\u044e \u0442\u0432\u043e\u0439 \u0440\u0430\u043d\u0434\u043e\u043c \u0441 3 \u0441\u0442\u0440\u043e\u043a!\u00bb<\/em><\/strong>:<\/p>\n<h2>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043c\u0430\u0433\u0438\u0438<\/h2>\n<pre><code>tst=# SELECT r random, magic(r) random_next FROM random() r;        random       |    random_next --------------------+--------------------  0.3921143477755571 | 0.6377947747296489  tst=# SELECT r random, magic(r) random_next FROM random() r;        random       |    random_next --------------------+--------------------  0.6377947747296489 | 0.5727554063674667  tst=# SELECT r random, magic(r) random_next FROM random() r;        random       |    random_next --------------------+--------------------  0.5727554063674667 | 0.4979625995285346<\/code><\/pre>\n<figure class=\"full-width\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/c2a\/254\/aa4\/c2a254aa4006d0e076816fbbb15f7e35.jpeg\" alt=\"\u0422\u044b \u0443\u0433\u0430\u0434\u0430\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 random \u043e\u0431\u0430 \u0440\u0430\u0437\u0430?..\" title=\"\u0422\u044b \u0443\u0433\u0430\u0434\u0430\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 random \u043e\u0431\u0430 \u0440\u0430\u0437\u0430?..\" width=\"850\" height=\"566\"><figcaption>\u0422\u044b \u0443\u0433\u0430\u0434\u0430\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 random \u043e\u0431\u0430 \u0440\u0430\u0437\u0430?..<\/figcaption><\/figure>\n<h2>\u0427\u0442\u043e \u0436\u0435 \u0442\u0430\u043c &#171;\u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c&#187;?<\/h2>\n<pre><code class=\"sql\">CREATE OR REPLACE FUNCTION magic(r double precision) RETURNS double precision AS $$   SELECT     (       (         (r &amp; x'FFFFFFFFFFFF'::bigint) * (mul &amp; x'000000000FFF'::bigint)       + (r &amp; x'000FFFFFFFFF'::bigint) * (mul &amp; x'000000FFF000'::bigint)       + (r &amp; x'000000FFFFFF'::bigint) * (mul &amp; x'000FFF000000'::bigint)       + (r &amp; x'000000000FFF'::bigint) * (mul &amp; x'FFF000000000'::bigint)       + add       ) &amp; x'FFFFFFFFFFFF'::bigint     )::double precision \/ x'1000000000000'::bigint   FROM     (VALUES(       (r * x'1000000000000'::bigint)::bigint     , x'0005deece66d'::bigint     , x'000b'::bigint     )) T(r, mul, add) $$ LANGUAGE sql;<\/code><\/pre>\n<p>\u041d\u043e \u043a\u0430\u043a \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442? \u041e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a <a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/12\/functions-math#FUNCTIONS-MATH-RANDOM-TABLE\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>:<\/p>\n<blockquote>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f&nbsp;<code>random()<\/code>&nbsp;\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 <strong>\u043b\u0438\u043d\u0435\u0439\u043d\u044b\u0439 \u043a\u043e\u043d\u0433\u0440\u0443\u044d\u043d\u0442\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c<\/strong>. \u041e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e, \u043d\u043e <strong>\u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439<\/strong>; \u0431\u043e\u043b\u0435\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0430\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432 \u043c\u043e\u0434\u0443\u043b\u0435&nbsp;<a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/12\/pgcrypto\">pgcrypto<\/a>. \u0415\u0441\u043b\u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439&nbsp;<code>setseed()<\/code>&nbsp;\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0451 \u0441 \u043e\u0434\u043d\u0438\u043c \u0438 \u0442\u0435\u043c \u0436\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432&nbsp;<code>random()<\/code>&nbsp;\u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0441\u0435\u0430\u043d\u0441\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u0441\u044f.  <\/p>\n<\/blockquote>\n<p>\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0443\u0431\u0435\u0434\u0438\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 &#171;\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0441\u0442\u0438 \u043d\u0435 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b&#187;, \u0442\u043e \u0434\u043b\u044f \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438 \u0442\u0443\u0442 \u043c\u0435\u0441\u0442\u0430 \u0442\u043e\u0447\u043d\u043e \u043d\u0435\u0442. \u041d\u043e \u0447\u0442\u043e \u044d\u0442\u043e \u0437\u0430 &#171;\u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043b\u0438\u043d\u0435\u0439\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c&#187;?<\/p>\n<figure class=\"\"><img loading=\"lazy\" decoding=\"async\" src=\"https:\/\/habrastorage.org\/getpro\/habr\/upload_files\/ef3\/e5b\/f39\/ef3e5bf39ba1fa364c3b78ac30c1bf55.jpeg\" alt=\"We Need To Go Deeper\" title=\"We Need To Go Deeper\" width=\"500\" height=\"333\"><figcaption>We Need To Go Deeper<\/figcaption><\/figure>\n<p>\u0418\u0434\u0435\u043c \u043d\u0430 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 <a href=\"https:\/\/github.com\/postgres\/postgres\">github-\u0437\u0435\u0440\u043a\u0430\u043b\u043e PostgreSQL<\/a> \u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 <code>setseed<\/code> \u0432 <a href=\"https:\/\/github.com\/postgres\/postgres\/blob\/REL_13_STABLE\/src\/backend\/utils\/adt\/float.c#L2694\">float.c<\/a>:<\/p>\n<pre><code class=\"cpp\">\/*  *\t\tsetseed\t\t- set seed for the random number generator  *\/ Datum setseed(PG_FUNCTION_ARGS) { \tfloat8\t\tseed = PG_GETARG_FLOAT8(0); \tuint64\t\tiseed;    \/\/ ...    \t\/* Use sign bit + 47 fractional bits to fill drandom_seed[] *\/ \tiseed = (int64) (seed * (float8) UINT64CONST(0x7FFFFFFFFFFF)); \tdrandom_seed[0] = (unsigned short) iseed; \tdrandom_seed[1] = (unsigned short) (iseed &gt;&gt; 16); \tdrandom_seed[2] = (unsigned short) (iseed &gt;&gt; 32); \tdrandom_seed_set = true;  \tPG_RETURN_VOID(); }<\/code><\/pre>\n<p>\u0423\u0436\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e &#8212; \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0437 <code>float8<\/code>-\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u0441\u0435\u0433\u043e <strong>48 \u0431\u0438\u0442<\/strong>.<\/p>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c\u0441\u044f <a href=\"https:\/\/github.com\/postgres\/postgres\/blob\/REL_13_STABLE\/src\/backend\/utils\/adt\/float.c#L2657\">\u0447\u0443\u0442\u044c \u0432\u044b\u0448\u0435<\/a>:<\/p>\n<pre><code class=\"cpp\">\/*  *\t\tdrandom\t\t- returns a random number  *\/ Datum drandom(PG_FUNCTION_ARGS) { \tfloat8\t\tresult;  \t\/* Initialize random seed, if not done yet in this process *\/ \tif (unlikely(!drandom_seed_set)) \t{ \t\t\/* \t\t * If possible, initialize the seed using high-quality random bits. \t\t * Should that fail for some reason, we fall back on a lower-quality \t\t * seed based on current time and PID. \t\t *\/ \t\tif (!pg_strong_random(drandom_seed, sizeof(drandom_seed))) \t\t{ \t\t\tTimestampTz now = GetCurrentTimestamp(); \t\t\tuint64\t\tiseed;  \t\t\t\/* Mix the PID with the most predictable bits of the timestamp *\/ \t\t\tiseed = (uint64) now ^ ((uint64) MyProcPid &lt;&lt; 32); \t\t\tdrandom_seed[0] = (unsigned short) iseed; \t\t\tdrandom_seed[1] = (unsigned short) (iseed &gt;&gt; 16); \t\t\tdrandom_seed[2] = (unsigned short) (iseed &gt;&gt; 32); \t\t} \t\tdrandom_seed_set = true; \t}    \t\/* pg_erand48 produces desired result range [0.0 - 1.0) *\/ \tresult = pg_erand48(drandom_seed);  \tPG_RETURN_FLOAT8(result); }<\/code><\/pre>\n<p>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>pg_erand48<\/code> \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u043c, \u0447\u0442\u043e \u043c\u044b \u043d\u0430 \u0432\u0435\u0440\u043d\u043e\u043c \u043f\u0443\u0442\u0438 &#8212; \u043d\u0430\u0439\u0434\u0435\u043c \u0435\u0435 \u0432 <a href=\"https:\/\/github.com\/postgres\/postgres\/blob\/REL_13_STABLE\/src\/port\/erand48.c#L83\">erand48.c<\/a>:<\/p>\n<pre><code class=\"cpp\">\/*  * Generate a random floating-point value using caller-supplied state.  * Values are uniformly distributed over the interval [0.0, 1.0).  *\/ double pg_erand48(unsigned short xseed[3]) { \tuint64\t\tx = _dorand48(xseed);  \treturn ldexp((double) (x &amp; UINT64CONST(0xFFFFFFFFFFFF)), -48); }<\/code><\/pre>\n<p>\u0415\u0449\u0435 \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c\u0441\u044f \u043d\u0430 \u0448\u0430\u0433 \u0437\u0430 <a href=\"https:\/\/github.com\/postgres\/postgres\/blob\/REL_13_STABLE\/src\/port\/erand48.c#L56\">_dorand48<\/a>:<\/p>\n<pre><code class=\"cpp\">\/* These values are specified by POSIX *\/ #define RAND48_MULT\t\tUINT64CONST(0x0005deece66d) #define RAND48_ADD\t\tUINT64CONST(0x000b)  \/* POSIX specifies 0x330e's use in srand48, but the other bits are arbitrary *\/ #define RAND48_SEED_0\t(0x330e) #define RAND48_SEED_1\t(0xabcd) #define RAND48_SEED_2\t(0x1234)  static unsigned short _rand48_seed[3] = { \tRAND48_SEED_0, \tRAND48_SEED_1, \tRAND48_SEED_2 };  \/*  * Advance the 48-bit value stored in xseed[] to the next \"random\" number.  *  * Also returns the value of that number --- without masking it to 48 bits.  * If caller uses the result, it must mask off the bits it wants.  *\/ static uint64 _dorand48(unsigned short xseed[3]) { \t\/* \t * We do the arithmetic in uint64; any type wider than 48 bits would work. \t *\/ \tuint64\t\tin; \tuint64\t\tout;  \tin = (uint64) xseed[2] &lt;&lt; 32 | (uint64) xseed[1] &lt;&lt; 16 | (uint64) xseed[0];  \tout = in * RAND48_MULT + RAND48_ADD;  \txseed[0] = out &amp; 0xFFFF; \txseed[1] = (out &gt;&gt; 16) &amp; 0xFFFF; \txseed[2] = (out &gt;&gt; 32) &amp; 0xFFFF;  \treturn out; }<\/code><\/pre>\n<p>\u0410 \u0432\u043e\u0442 \u0438 \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b!<\/p>\n<h2>\u0422\u0430\u043a \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 random()?<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 random().<\/p>\n<h4>&#171;\u041f\u043e\u0441\u0435\u0432&#187;<\/h4>\n<p>\u041f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435 <code>random()<\/code> \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 PostgreSQL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 <strong>\u0442\u0440\u0438 16-\u0431\u0438\u0442\u043d\u044b\u0445 \u0441\u043b\u043e\u0432\u0430<\/strong> (48 \u0431\u0438\u0442) \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 <code>now<\/code>-\u0442\u0430\u0439\u043c\u0441\u0442\u0430\u043c\u043f\u0430 &#171;\u043f\u0440\u043e\u043a\u0441\u043e\u0440\u0435\u043d\u043d\u044b\u0445&#187; \u0441 PID \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430:<\/p>\n<pre><code class=\"cpp\">\t\t\tTimestampTz now = GetCurrentTimestamp(); \t\t\tuint64\t\tiseed;  \t\t\t\/* Mix the PID with the most predictable bits of the timestamp *\/ \t\t\tiseed = (uint64) now ^ ((uint64) MyProcPid &lt;&lt; 32); \t\t\tdrandom_seed[0] = (unsigned short) iseed; \t\t\tdrandom_seed[1] = (unsigned short) (iseed &gt;&gt; 16); \t\t\tdrandom_seed[2] = (unsigned short) (iseed &gt;&gt; 32);<\/code><\/pre>\n<p>\u0412 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u043c\u043e\u0436\u043d\u043e &#171;\u0437\u0430\u0441\u0435\u044f\u0442\u044c&#187; \u0441\u0432\u043e\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>setseed<\/code>.<\/p>\n<h4>\u0428\u0430\u0433 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439<\/h4>\n<p>\u041f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u044d\u0442\u043e\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u0435\u0434\u0438\u043d\u043e\u0435 48-\u0431\u0438\u0442\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 <strong>\u0443\u043c\u043d\u043e\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 <\/strong><code>RAND48_MULT (<\/code><strong>0x0005deece66d<\/strong><code>)<\/code><strong> \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f <\/strong><code>RAND48_ADD (<\/code><strong>0x000b<\/strong><code>)<\/code>.<\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 <code>double<\/code>, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0435\u0433\u043e \u0438\u0437 \u043c\u043b\u0430\u0434\u0448\u0438\u0445 48 \u0431\u0438\u0442.<\/p>\n<h2>\u042d\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u043c \u0448\u0430\u0433 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u043d\u0430 SQL<\/h2>\n<p>\u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043d\u0430\u0434\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0437\u044f\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>random()<\/code>, \u0443\u043c\u043d\u043e\u0436\u0438\u0442\u044c  \u0434\u0430 \u0441\u043b\u043e\u0436\u0438\u0442\u044c, \u043d\u043e \u0435\u0441\u0442\u044c \u043d\u044e\u0430\u043d\u0441\u044b.<\/p>\n<h4>double precision (double) &lt;-&gt; bigint (uint64)<\/h4>\n<p>\u0412 C-\u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0430\u0445 \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u043e \u043a\u0430\u043a <code>doubl\u0435<\/code>,\u0442\u043e \u043a\u0430\u043a <code>uint64<\/code> &#8212; \u0432 SQL \u043c\u044b \u0442\u0430\u043a \u043d\u0435 \u043c\u043e\u0436\u0435\u043c. \u0417\u0430\u0442\u043e \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438\u0437\u0432\u0430\u0442\u044c \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u0437\u043d\u0430\u043d\u0438\u0435 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A7%D0%B8%D1%81%D0%BB%D0%BE_%D1%81_%D0%BF%D0%BB%D0%B0%D0%B2%D0%B0%D1%8E%D1%89%D0%B5%D0%B9_%D0%B7%D0%B0%D0%BF%D1%8F%D1%82%D0%BE%D0%B9#%D0%94%D0%B8%D0%B0%D0%BF%D0%B0%D0%B7%D0%BE%D0%BD_%D1%87%D0%B8%D1%81%D0%B5%D0%BB,_%D0%BF%D1%80%D0%B5%D0%B4%D1%81%D1%82%D0%B0%D0%B2%D0%B8%D0%BC%D1%8B%D1%85_%D0%B2_%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B5_%D1%81_%D0%BF%D0%BB%D0%B0%D0%B2%D0%B0%D1%8E%D1%89%D0%B5%D0%B9_%D0%B7%D0%B0%D0%BF%D1%8F%D1%82%D0%BE%D0%B9\">\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0447\u0438\u0441\u0435\u043b \u0441 \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 IEEE754<\/a> \u0438 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0443.<\/p>\n<p>\u041f\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0443, \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043c\u0430\u043d\u0442\u0438\u0441\u0441\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043c\u043b\u0430\u0434\u0448\u0438\u0435 52 \u0431\u0438\u0442\u0430. \u0422\u043e \u0435\u0441\u0442\u044c \u043d\u0430\u0448 48-\u0431\u0438\u0442\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 <code>double precision<\/code> \u043f\u0440\u044f\u043c\u043e \u0442\u0430\u043c \u0438 \u043b\u0435\u0436\u0438\u0442, \u043f\u0440\u0438\u0447\u0435\u043c \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043e\u0431\u043d\u0443\u043b\u0435\u043d &#8212; \u0430, \u0437\u043d\u0430\u0447\u0438\u0442, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e <strong>\u0443\u043c\u043d\u043e\u0436\u0438\u0442\u044c \u0435\u0433\u043e \u043d\u0430 2^48<\/strong>, \u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 <code>bigint<\/code>-\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"sql\">SELECT (r::double precision * x'1000000000000'::bigint)::bigint;<\/code><\/pre>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443:<\/p>\n<pre><code class=\"sql\">SELECT r::double precision \/ x'1000000000000'::bigint;<\/code><\/pre>\n<h4>\u041f\u0441\u0435\u0432\u0434\u043e\u0434\u043b\u0438\u043d\u043d\u0430\u044f \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u043a\u0430<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u0438\u0448\u044c \u0443\u043c\u043d\u043e\u0436\u0438\u0442\u044c \u043d\u0430 <strong>0x0005deece66d<\/strong>, \u0438&#8230;<\/p>\n<pre><code>\u041e\u0428\u0418\u0411\u041a\u0410:  bigint \u0432\u043d\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430<\/code><\/pre>\n<p>\u0412\u043f\u043e\u043b\u043d\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e &#8212; \u0432\u0437\u044f\u043b\u0438 48-\u0431\u0438\u0442\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e, \u0443\u043c\u043d\u043e\u0436\u0438\u043b\u0438 \u043d\u0430 35-\u0431\u0438\u0442\u043d\u043e\u0435 &#8212; <strong>\u0432 64 \u0431\u0438\u0442\u0430 \u043d\u0435 \u0432\u043b\u0435\u0437\u043b\u0438<\/strong>.<\/p>\n<p>\u041d\u043e \u043d\u0430\u043c \u0436\u0435 \u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u0430\u0436\u0435 64 \u0431\u0438\u0442\u0430 &#8212; \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u043c\u043b\u0430\u0434\u0448\u0438\u0435 48! \u0423\u043c\u043d\u043e\u0436\u0438\u043c \u043d\u0430\u0448\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f &#171;\u0441\u0442\u043e\u043b\u0431\u0438\u043a\u043e\u043c&#187; \u043a\u0430\u043a <strong>12-\u0431\u0438\u0442\u043d\u044b\u0435 \u0441\u043b\u043e\u0432\u0430<\/strong> (\u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 16-\u0431\u0438\u0442\u043d\u044b\u0435 \u0432\u0441\u0435-\u0442\u0430\u043a\u0438 \u043f\u0440\u0438 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0438 \u0432\u044b\u043b\u0435\u0437\u0430\u044e\u0442 \u0432 \u0437\u043d\u0430\u043a\u043e\u0432\u044b\u0439 \u0431\u0438\u0442) \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0437\u0440\u044f\u0434\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code>         12 12 12 12 48 bit =  A  B  C  D         * E  F  G  H --------------------         |AH BH CH DH = A B C D * 0 0 0 H       AG|BG CG DG    = 0 B C D * 0 0 G 0    AF BF|CF DF       = 0 0 C D * 0 F 0 0 AE BE CE|DE          = 0 0 0 D * E 0 0 0<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u044d\u0442\u043e \u0432\u0441\u0435 \u0441\u043b\u043e\u0436\u0438\u0442\u044c, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c <strong>0x000b<\/strong>, \u043e\u0442\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u0441\u0442\u0430\u0440\u0448\u0438\u0435 \u0431\u0438\u0442\u044b \u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c, \u0438 &#8212; \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b \u0443\u0436\u0435 \u0432\u0438\u0434\u0435\u043b\u0438 \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/tensor\/blog\/547108\/\"> https:\/\/habr.com\/ru\/company\/tensor\/blog\/547108\/<\/a><\/p>\n","protected":false},"excerpt":{"rendered":"\n<div class=\"post__text post__text_v2\" id=\"post-content-body\">\n<figure class=\"full-width\"><figcaption><\/figcaption><\/figure>\n<p>\u041c\u043e\u0436\u043d\u043e \u043b\u0438 \u0434\u043e\u0441\u0442\u043e\u0432\u0435\u0440\u043d\u043e \u043f\u0440\u0435\u0434\u0441\u043a\u0430\u0437\u0430\u0442\u044c \u0431\u0443\u0434\u0443\u0449\u0435\u0435 \u0445\u043e\u0442\u044c \u043d\u0430 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0432\u043f\u0435\u0440\u0435\u0434? \u0418\u043d\u043e\u0433\u0434\u0430 &#8212; \u0432\u043f\u043e\u043b\u043d\u0435, \u043d\u0430\u0434\u043e \u0442\u043e\u043b\u044c\u043a\u043e \u043c\u043d\u043e\u0433\u043e \u0432\u0435\u0437\u0435\u043d\u0438\u044f&#8230; \u0438\u043b\u0438 \u043d\u0435\u043c\u043d\u043e\u0433\u043e \u0437\u043d\u0430\u043d\u0438\u0439.<\/p>\n<p>\u0421\u0435\u0433\u043e\u0434\u043d\u044f \u043f\u0440\u043e\u043d\u0430\u0431\u043b\u044e\u0434\u0430\u0435\u043c \u0441\u0435\u0430\u043d\u0441 \u0447\u0435\u0440\u043d\u043e\u0439 \u043c\u0430\u0433\u0438\u0438 \u0441 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u043c \u0440\u0430\u0437\u043e\u0431\u043b\u0430\u0447\u0435\u043d\u0438\u0435\u043c, \u0438\u043b\u0438 <strong><em>\u00ab\u042f \u0443\u0433\u0430\u0434\u0430\u044e \u0442\u0432\u043e\u0439 \u0440\u0430\u043d\u0434\u043e\u043c \u0441 3 \u0441\u0442\u0440\u043e\u043a!\u00bb<\/em><\/strong>:<\/p>\n<h2>\u041d\u0435\u043c\u043d\u043e\u0433\u043e \u043c\u0430\u0433\u0438\u0438<\/h2>\n<pre><code>tst=# SELECT r random, magic(r) random_next FROM random() r;        random       |    random_next --------------------+--------------------  0.3921143477755571 | 0.6377947747296489  tst=# SELECT r random, magic(r) random_next FROM random() r;        random       |    random_next --------------------+--------------------  0.6377947747296489 | 0.5727554063674667  tst=# SELECT r random, magic(r) random_next FROM random() r;        random       |    random_next --------------------+--------------------  0.5727554063674667 | 0.4979625995285346<\/code><\/pre>\n<figure class=\"full-width\"><figcaption>\u0422\u044b \u0443\u0433\u0430\u0434\u0430\u043b \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0439 random \u043e\u0431\u0430 \u0440\u0430\u0437\u0430?..<\/figcaption><\/figure>\n<h2>\u0427\u0442\u043e \u0436\u0435 \u0442\u0430\u043c &#171;\u043f\u043e\u0434 \u043a\u0430\u043f\u043e\u0442\u043e\u043c&#187;?<\/h2>\n<pre><code class=\"sql\">CREATE OR REPLACE FUNCTION magic(r double precision) RETURNS double precision AS $$   SELECT     (       (         (r &amp; x'FFFFFFFFFFFF'::bigint) * (mul &amp; x'000000000FFF'::bigint)       + (r &amp; x'000FFFFFFFFF'::bigint) * (mul &amp; x'000000FFF000'::bigint)       + (r &amp; x'000000FFFFFF'::bigint) * (mul &amp; x'000FFF000000'::bigint)       + (r &amp; x'000000000FFF'::bigint) * (mul &amp; x'FFF000000000'::bigint)       + add       ) &amp; x'FFFFFFFFFFFF'::bigint     )::double precision \/ x'1000000000000'::bigint   FROM     (VALUES(       (r * x'1000000000000'::bigint)::bigint     , x'0005deece66d'::bigint     , x'000b'::bigint     )) T(r, mul, add) $$ LANGUAGE sql;<\/code><\/pre>\n<p>\u041d\u043e \u043a\u0430\u043a \u0438 \u043f\u043e\u0447\u0435\u043c\u0443 \u044d\u0442\u043e \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442? \u041e\u0431\u0440\u0430\u0442\u0438\u043c\u0441\u044f \u043a <a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/12\/functions-math#FUNCTIONS-MATH-RANDOM-TABLE\">\u0434\u043e\u043a\u0443\u043c\u0435\u043d\u0442\u0430\u0446\u0438\u0438<\/a>:<\/p>\n<blockquote>\n<p>\u0424\u0443\u043d\u043a\u0446\u0438\u044f&nbsp;<code>random()<\/code>&nbsp;\u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442 \u043f\u0440\u043e\u0441\u0442\u043e\u0439 <strong>\u043b\u0438\u043d\u0435\u0439\u043d\u044b\u0439 \u043a\u043e\u043d\u0433\u0440\u0443\u044d\u043d\u0442\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c<\/strong>. \u041e\u043d\u0430 \u0440\u0430\u0431\u043e\u0442\u0430\u0435\u0442 \u0431\u044b\u0441\u0442\u0440\u043e, \u043d\u043e <strong>\u043d\u0435 \u043f\u043e\u0434\u0445\u043e\u0434\u0438\u0442 \u0434\u043b\u044f \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0447\u0435\u0441\u043a\u0438\u0445 \u043f\u0440\u0438\u043b\u043e\u0436\u0435\u043d\u0438\u0439<\/strong>; \u0431\u043e\u043b\u0435\u0435 \u0431\u0435\u0437\u043e\u043f\u0430\u0441\u043d\u0430\u044f \u0430\u043b\u044c\u0442\u0435\u0440\u043d\u0430\u0442\u0438\u0432\u0430 \u0438\u043c\u0435\u0435\u0442\u0441\u044f \u0432 \u043c\u043e\u0434\u0443\u043b\u0435&nbsp;<a href=\"https:\/\/postgrespro.ru\/docs\/postgresql\/12\/pgcrypto\">pgcrypto<\/a>. \u0415\u0441\u043b\u0438 \u0432\u043e\u0441\u043f\u043e\u043b\u044c\u0437\u043e\u0432\u0430\u0442\u044c\u0441\u044f \u0444\u0443\u043d\u043a\u0446\u0438\u0435\u0439&nbsp;<code>setseed()<\/code>&nbsp;\u0438 \u0432\u044b\u0437\u044b\u0432\u0430\u0442\u044c \u0435\u0451 \u0441 \u043e\u0434\u043d\u0438\u043c \u0438 \u0442\u0435\u043c \u0436\u0435 \u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u043e\u043c, \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442\u044b \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0438\u0445 \u0432\u044b\u0437\u043e\u0432\u043e\u0432&nbsp;<code>random()<\/code>&nbsp;\u0432 \u0442\u0435\u043a\u0443\u0449\u0435\u043c \u0441\u0435\u0430\u043d\u0441\u0435 \u0431\u0443\u0434\u0443\u0442 \u043f\u043e\u0432\u0442\u043e\u0440\u044f\u0442\u044c\u0441\u044f.  <\/p>\n<\/blockquote>\n<p>\u0421\u043e\u0431\u0441\u0442\u0432\u0435\u043d\u043d\u043e, \u043c\u044b \u0442\u043e\u043b\u044c\u043a\u043e \u0447\u0442\u043e \u0443\u0431\u0435\u0434\u0438\u043b\u0438\u0441\u044c, \u0447\u0442\u043e \u0435\u0441\u043b\u0438 &#171;\u0441\u043b\u0443\u0447\u0430\u0439\u043d\u043e\u0441\u0442\u0438 \u043d\u0435 \u0441\u043b\u0443\u0447\u0430\u0439\u043d\u044b&#187;, \u0442\u043e \u0434\u043b\u044f \u043a\u0440\u0438\u043f\u0442\u043e\u0433\u0440\u0430\u0444\u0438\u0438 \u0442\u0443\u0442 \u043c\u0435\u0441\u0442\u0430 \u0442\u043e\u0447\u043d\u043e \u043d\u0435\u0442. \u041d\u043e \u0447\u0442\u043e \u044d\u0442\u043e \u0437\u0430 &#171;\u043f\u0440\u043e\u0441\u0442\u043e\u0439 \u043b\u0438\u043d\u0435\u0439\u043d\u044b\u0439 \u0430\u043b\u0433\u043e\u0440\u0438\u0442\u043c&#187;?<\/p>\n<figure class=\"\"><figcaption>We Need To Go Deeper<\/figcaption><\/figure>\n<p>\u0418\u0434\u0435\u043c \u043d\u0430 \u043e\u0444\u0438\u0446\u0438\u0430\u043b\u044c\u043d\u043e\u0435 <a href=\"https:\/\/github.com\/postgres\/postgres\">github-\u0437\u0435\u0440\u043a\u0430\u043b\u043e PostgreSQL<\/a> \u0438 \u043d\u0430\u0445\u043e\u0434\u0438\u043c \u043e\u043f\u0440\u0435\u0434\u0435\u043b\u0435\u043d\u0438\u0435 <code>setseed<\/code> \u0432 <a href=\"https:\/\/github.com\/postgres\/postgres\/blob\/REL_13_STABLE\/src\/backend\/utils\/adt\/float.c#L2694\">float.c<\/a>:<\/p>\n<pre><code class=\"cpp\">\/*  *\t\tsetseed\t\t- set seed for the random number generator  *\/ Datum setseed(PG_FUNCTION_ARGS) { \tfloat8\t\tseed = PG_GETARG_FLOAT8(0); \tuint64\t\tiseed;    \/\/ ...    \t\/* Use sign bit + 47 fractional bits to fill drandom_seed[] *\/ \tiseed = (int64) (seed * (float8) UINT64CONST(0x7FFFFFFFFFFF)); \tdrandom_seed[0] = (unsigned short) iseed; \tdrandom_seed[1] = (unsigned short) (iseed &gt;&gt; 16); \tdrandom_seed[2] = (unsigned short) (iseed &gt;&gt; 32); \tdrandom_seed_set = true;  \tPG_RETURN_VOID(); }<\/code><\/pre>\n<p>\u0423\u0436\u0435 \u0438\u043d\u0442\u0435\u0440\u0435\u0441\u043d\u043e &#8212; \u043e\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442\u0441\u044f \u0438\u0437 <code>float8<\/code>-\u0430\u0440\u0433\u0443\u043c\u0435\u043d\u0442\u0430 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u0435\u0442\u0441\u044f \u0432\u0441\u0435\u0433\u043e <strong>48 \u0431\u0438\u0442<\/strong>.<\/p>\n<p>\u0410 \u0442\u0435\u043f\u0435\u0440\u044c \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c\u0441\u044f <a href=\"https:\/\/github.com\/postgres\/postgres\/blob\/REL_13_STABLE\/src\/backend\/utils\/adt\/float.c#L2657\">\u0447\u0443\u0442\u044c \u0432\u044b\u0448\u0435<\/a>:<\/p>\n<pre><code class=\"cpp\">\/*  *\t\tdrandom\t\t- returns a random number  *\/ Datum drandom(PG_FUNCTION_ARGS) { \tfloat8\t\tresult;  \t\/* Initialize random seed, if not done yet in this process *\/ \tif (unlikely(!drandom_seed_set)) \t{ \t\t\/* \t\t * If possible, initialize the seed using high-quality random bits. \t\t * Should that fail for some reason, we fall back on a lower-quality \t\t * seed based on current time and PID. \t\t *\/ \t\tif (!pg_strong_random(drandom_seed, sizeof(drandom_seed))) \t\t{ \t\t\tTimestampTz now = GetCurrentTimestamp(); \t\t\tuint64\t\tiseed;  \t\t\t\/* Mix the PID with the most predictable bits of the timestamp *\/ \t\t\tiseed = (uint64) now ^ ((uint64) MyProcPid &lt;&lt; 32); \t\t\tdrandom_seed[0] = (unsigned short) iseed; \t\t\tdrandom_seed[1] = (unsigned short) (iseed &gt;&gt; 16); \t\t\tdrandom_seed[2] = (unsigned short) (iseed &gt;&gt; 32); \t\t} \t\tdrandom_seed_set = true; \t}    \t\/* pg_erand48 produces desired result range [0.0 - 1.0) *\/ \tresult = pg_erand48(drandom_seed);  \tPG_RETURN_FLOAT8(result); }<\/code><\/pre>\n<p>\u041d\u0430\u0437\u0432\u0430\u043d\u0438\u0435 \u0444\u0443\u043d\u043a\u0446\u0438\u0438 <code>pg_erand48<\/code> \u043f\u043e\u0434\u0441\u043a\u0430\u0437\u044b\u0432\u0430\u0435\u0442 \u043d\u0430\u043c, \u0447\u0442\u043e \u043c\u044b \u043d\u0430 \u0432\u0435\u0440\u043d\u043e\u043c \u043f\u0443\u0442\u0438 &#8212; \u043d\u0430\u0439\u0434\u0435\u043c \u0435\u0435 \u0432 <a href=\"https:\/\/github.com\/postgres\/postgres\/blob\/REL_13_STABLE\/src\/port\/erand48.c#L83\">erand48.c<\/a>:<\/p>\n<pre><code class=\"cpp\">\/*  * Generate a random floating-point value using caller-supplied state.  * Values are uniformly distributed over the interval [0.0, 1.0).  *\/ double pg_erand48(unsigned short xseed[3]) { \tuint64\t\tx = _dorand48(xseed);  \treturn ldexp((double) (x &amp; UINT64CONST(0xFFFFFFFFFFFF)), -48); }<\/code><\/pre>\n<p>\u0415\u0449\u0435 \u043f\u043e\u0434\u043d\u0438\u043c\u0435\u043c\u0441\u044f \u043d\u0430 \u0448\u0430\u0433 \u0437\u0430 <a href=\"https:\/\/github.com\/postgres\/postgres\/blob\/REL_13_STABLE\/src\/port\/erand48.c#L56\">_dorand48<\/a>:<\/p>\n<pre><code class=\"cpp\">\/* These values are specified by POSIX *\/ #define RAND48_MULT\t\tUINT64CONST(0x0005deece66d) #define RAND48_ADD\t\tUINT64CONST(0x000b)  \/* POSIX specifies 0x330e's use in srand48, but the other bits are arbitrary *\/ #define RAND48_SEED_0\t(0x330e) #define RAND48_SEED_1\t(0xabcd) #define RAND48_SEED_2\t(0x1234)  static unsigned short _rand48_seed[3] = { \tRAND48_SEED_0, \tRAND48_SEED_1, \tRAND48_SEED_2 };  \/*  * Advance the 48-bit value stored in xseed[] to the next \"random\" number.  *  * Also returns the value of that number --- without masking it to 48 bits.  * If caller uses the result, it must mask off the bits it wants.  *\/ static uint64 _dorand48(unsigned short xseed[3]) { \t\/* \t * We do the arithmetic in uint64; any type wider than 48 bits would work. \t *\/ \tuint64\t\tin; \tuint64\t\tout;  \tin = (uint64) xseed[2] &lt;&lt; 32 | (uint64) xseed[1] &lt;&lt; 16 | (uint64) xseed[0];  \tout = in * RAND48_MULT + RAND48_ADD;  \txseed[0] = out &amp; 0xFFFF; \txseed[1] = (out &gt;&gt; 16) &amp; 0xFFFF; \txseed[2] = (out &gt;&gt; 32) &amp; 0xFFFF;  \treturn out; }<\/code><\/pre>\n<p>\u0410 \u0432\u043e\u0442 \u0438 \u0432\u043e\u043b\u0448\u0435\u0431\u043d\u044b\u0435 \u043a\u043e\u043d\u0441\u0442\u0430\u043d\u0442\u044b!<\/p>\n<h2>\u0422\u0430\u043a \u0447\u0442\u043e \u0442\u0430\u043a\u043e\u0435 random()?<\/h2>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0443 \u043d\u0430\u0441 \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u0438\u043d\u0444\u043e\u0440\u043c\u0430\u0446\u0438\u0438, \u0447\u0442\u043e\u0431\u044b \u043f\u043e\u043d\u044f\u0442\u044c, \u043a\u0430\u043a \u0432\u044b\u0447\u0438\u0441\u043b\u044f\u0435\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 random().<\/p>\n<h4>&#171;\u041f\u043e\u0441\u0435\u0432&#187;<\/h4>\n<p>\u041f\u0440\u0438 \u043f\u0435\u0440\u0432\u043e\u043c \u0437\u0430\u043f\u0440\u043e\u0441\u0435 <code>random()<\/code> \u0432 \u0440\u0430\u043c\u043a\u0430\u0445 PostgreSQL-\u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430 <strong>\u0442\u0440\u0438 16-\u0431\u0438\u0442\u043d\u044b\u0445 \u0441\u043b\u043e\u0432\u0430<\/strong> (48 \u0431\u0438\u0442) \u0438\u043d\u0438\u0446\u0438\u0430\u043b\u0438\u0437\u0438\u0440\u0443\u044e\u0442\u0441\u044f \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f\u043c\u0438 <code>now<\/code>-\u0442\u0430\u0439\u043c\u0441\u0442\u0430\u043c\u043f\u0430 &#171;\u043f\u0440\u043e\u043a\u0441\u043e\u0440\u0435\u043d\u043d\u044b\u0445&#187; \u0441 PID \u043f\u0440\u043e\u0446\u0435\u0441\u0441\u0430:<\/p>\n<pre><code class=\"cpp\">\t\t\tTimestampTz now = GetCurrentTimestamp(); \t\t\tuint64\t\tiseed;  \t\t\t\/* Mix the PID with the most predictable bits of the timestamp *\/ \t\t\tiseed = (uint64) now ^ ((uint64) MyProcPid &lt;&lt; 32); \t\t\tdrandom_seed[0] = (unsigned short) iseed; \t\t\tdrandom_seed[1] = (unsigned short) (iseed &gt;&gt; 16); \t\t\tdrandom_seed[2] = (unsigned short) (iseed &gt;&gt; 32);<\/code><\/pre>\n<p>\u0412 \u043f\u043e\u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u0438\u043c\u0435\u043d\u043d\u043e \u044d\u0442\u043e\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u043c\u043e\u0436\u043d\u043e &#171;\u0437\u0430\u0441\u0435\u044f\u0442\u044c&#187; \u0441\u0432\u043e\u0438\u043c \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435\u043c \u0441 \u043f\u043e\u043c\u043e\u0449\u044c\u044e <code>setseed<\/code>.<\/p>\n<h4>\u0428\u0430\u0433 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439<\/h4>\n<p>\u041f\u0440\u0438 \u043a\u0430\u0436\u0434\u043e\u043c \u0441\u043b\u0435\u0434\u0443\u044e\u0449\u0435\u043c \u043e\u0431\u0440\u0430\u0449\u0435\u043d\u0438\u0438 \u044d\u0442\u043e\u0442 \u043c\u0430\u0441\u0441\u0438\u0432 \u0440\u0430\u0441\u0441\u043c\u0430\u0442\u0440\u0438\u0432\u0430\u044e\u0442\u0441\u044f \u043a\u0430\u043a \u0435\u0434\u0438\u043d\u043e\u0435 48-\u0431\u0438\u0442\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e, \u043a\u043e\u0442\u043e\u0440\u043e\u0435 <strong>\u0443\u043c\u043d\u043e\u0436\u0430\u0435\u0442\u0441\u044f \u043d\u0430 <\/strong><code>RAND48_MULT (<\/code><strong>0x0005deece66d<\/strong><code>)<\/code><strong> \u0438 \u0434\u043e\u0431\u0430\u0432\u043b\u044f\u0435\u0442\u0441\u044f <\/strong><code>RAND48_ADD (<\/code><strong>0x000b<\/strong><code>)<\/code>.<\/p>\n<p>\u0420\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0441\u043e\u0445\u0440\u0430\u043d\u044f\u0435\u0442\u0441\u044f \u043e\u0431\u0440\u0430\u0442\u043d\u043e \u0438 \u0432\u043e\u0437\u0432\u0440\u0430\u0449\u0430\u0435\u0442\u0441\u044f \u0432 \u0432\u0438\u0434\u0435 <code>double<\/code>, \u0441\u043e\u0441\u0442\u043e\u044f\u0449\u0435\u0433\u043e \u0438\u0437 \u043c\u043b\u0430\u0434\u0448\u0438\u0445 48 \u0431\u0438\u0442.<\/p>\n<h2>\u042d\u043c\u0443\u043b\u0438\u0440\u0443\u0435\u043c \u0448\u0430\u0433 \u0432\u044b\u0447\u0438\u0441\u043b\u0435\u043d\u0438\u0439 \u043d\u0430 SQL<\/h2>\n<p>\u0424\u0430\u043a\u0442\u0438\u0447\u0435\u0441\u043a\u0438, \u043d\u0430\u0434\u043e \u043f\u0440\u043e\u0441\u0442\u043e \u0432\u0437\u044f\u0442\u044c \u043f\u043e\u0441\u043b\u0435\u0434\u043d\u0435\u0435 \u0438\u0437\u0432\u0435\u0441\u0442\u043d\u043e\u0435 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u0435 <code>random()<\/code>, \u0443\u043c\u043d\u043e\u0436\u0438\u0442\u044c  \u0434\u0430 \u0441\u043b\u043e\u0436\u0438\u0442\u044c, \u043d\u043e \u0435\u0441\u0442\u044c \u043d\u044e\u0430\u043d\u0441\u044b.<\/p>\n<h4>double precision (double) &lt;-&gt; bigint (uint64)<\/h4>\n<p>\u0412 C-\u0438\u0441\u0445\u043e\u0434\u043d\u0438\u043a\u0430\u0445 \u043e\u0434\u043d\u0438 \u0438 \u0442\u0435 \u0436\u0435 \u0434\u0432\u043e\u0438\u0447\u043d\u044b\u0435 \u0434\u0430\u043d\u043d\u044b\u0435 \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u0442\u043e \u043a\u0430\u043a <code>doubl\u0435<\/code>,\u0442\u043e \u043a\u0430\u043a <code>uint64<\/code> &#8212; \u0432 SQL \u043c\u044b \u0442\u0430\u043a \u043d\u0435 \u043c\u043e\u0436\u0435\u043c. \u0417\u0430\u0442\u043e \u043c\u043e\u0436\u0435\u043c \u043f\u0440\u0438\u0437\u0432\u0430\u0442\u044c \u043d\u0430 \u043f\u043e\u043c\u043e\u0449\u044c \u0437\u043d\u0430\u043d\u0438\u0435 <a href=\"https:\/\/ru.wikipedia.org\/wiki\/%D0%A7%D0%B8%D1%81%D0%BB%D0%BE_%D1%81_%D0%BF%D0%BB%D0%B0%D0%B2%D0%B0%D1%8E%D1%89%D0%B5%D0%B9_%D0%B7%D0%B0%D0%BF%D1%8F%D1%82%D0%BE%D0%B9#%D0%94%D0%B8%D0%B0%D0%BF%D0%B0%D0%B7%D0%BE%D0%BD_%D1%87%D0%B8%D1%81%D0%B5%D0%BB,_%D0%BF%D1%80%D0%B5%D0%B4%D1%81%D1%82%D0%B0%D0%B2%D0%B8%D0%BC%D1%8B%D1%85_%D0%B2_%D1%84%D0%BE%D1%80%D0%BC%D0%B0%D1%82%D0%B5_%D1%81_%D0%BF%D0%BB%D0%B0%D0%B2%D0%B0%D1%8E%D1%89%D0%B5%D0%B9_%D0%B7%D0%B0%D0%BF%D1%8F%D1%82%D0%BE%D0%B9\">\u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0430 \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u0447\u0438\u0441\u0435\u043b \u0441 \u043f\u043b\u0430\u0432\u0430\u044e\u0449\u0435\u0439 \u0442\u043e\u0447\u043a\u043e\u0439 IEEE754<\/a> \u0438 \u043c\u0430\u0442\u0435\u043c\u0430\u0442\u0438\u043a\u0443.<\/p>\n<p>\u041f\u043e \u0441\u0442\u0430\u043d\u0434\u0430\u0440\u0442\u0443, \u0434\u043b\u044f \u0445\u0440\u0430\u043d\u0435\u043d\u0438\u044f \u043c\u0430\u043d\u0442\u0438\u0441\u0441\u044b \u0438\u0441\u043f\u043e\u043b\u044c\u0437\u0443\u044e\u0442\u0441\u044f \u043c\u043b\u0430\u0434\u0448\u0438\u0435 52 \u0431\u0438\u0442\u0430. \u0422\u043e \u0435\u0441\u0442\u044c \u043d\u0430\u0448 48-\u0431\u0438\u0442\u043d\u044b\u0439 \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 <code>double precision<\/code> \u043f\u0440\u044f\u043c\u043e \u0442\u0430\u043c \u0438 \u043b\u0435\u0436\u0438\u0442, \u043f\u0440\u0438\u0447\u0435\u043c \u043f\u043e\u0440\u044f\u0434\u043e\u043a \u043e\u0431\u043d\u0443\u043b\u0435\u043d &#8212; \u0430, \u0437\u043d\u0430\u0447\u0438\u0442, \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e <strong>\u0443\u043c\u043d\u043e\u0436\u0438\u0442\u044c \u0435\u0433\u043e \u043d\u0430 2^48<\/strong>, \u0438 \u043c\u044b \u043f\u043e\u043b\u0443\u0447\u0438\u043c \u0446\u0435\u043b\u043e\u0447\u0438\u0441\u043b\u0435\u043d\u043d\u043e\u0435 <code>bigint<\/code>-\u043f\u0440\u0435\u0434\u0441\u0442\u0430\u0432\u043b\u0435\u043d\u0438\u0435:<\/p>\n<pre><code class=\"sql\">SELECT (r::double precision * x'1000000000000'::bigint)::bigint;<\/code><\/pre>\n<p>\u0410\u043d\u0430\u043b\u043e\u0433\u0438\u0447\u043d\u043e \u0432 \u043e\u0431\u0440\u0430\u0442\u043d\u0443\u044e \u0441\u0442\u043e\u0440\u043e\u043d\u0443:<\/p>\n<pre><code class=\"sql\">SELECT r::double precision \/ x'1000000000000'::bigint;<\/code><\/pre>\n<h4>\u041f\u0441\u0435\u0432\u0434\u043e\u0434\u043b\u0438\u043d\u043d\u0430\u044f \u0430\u0440\u0438\u0444\u043c\u0435\u0442\u0438\u043a\u0430<\/h4>\n<p>\u0422\u0435\u043f\u0435\u0440\u044c \u0434\u043e\u0441\u0442\u0430\u0442\u043e\u0447\u043d\u043e \u043b\u0438\u0448\u044c \u0443\u043c\u043d\u043e\u0436\u0438\u0442\u044c \u043d\u0430 <strong>0x0005deece66d<\/strong>, \u0438&#8230;<\/p>\n<pre><code>\u041e\u0428\u0418\u0411\u041a\u0410:  bigint \u0432\u043d\u0435 \u0434\u0438\u0430\u043f\u0430\u0437\u043e\u043d\u0430<\/code><\/pre>\n<p>\u0412\u043f\u043e\u043b\u043d\u0435 \u043f\u043e\u043d\u044f\u0442\u043d\u043e &#8212; \u0432\u0437\u044f\u043b\u0438 48-\u0431\u0438\u0442\u043d\u043e\u0435 \u0447\u0438\u0441\u043b\u043e, \u0443\u043c\u043d\u043e\u0436\u0438\u043b\u0438 \u043d\u0430 35-\u0431\u0438\u0442\u043d\u043e\u0435 &#8212; <strong>\u0432 64 \u0431\u0438\u0442\u0430 \u043d\u0435 \u0432\u043b\u0435\u0437\u043b\u0438<\/strong>.<\/p>\n<p>\u041d\u043e \u043d\u0430\u043c \u0436\u0435 \u0438 \u043d\u0435 \u043d\u0443\u0436\u043d\u043e \u0434\u0430\u0436\u0435 64 \u0431\u0438\u0442\u0430 &#8212; \u0432\u0441\u0435\u0433\u043e \u043b\u0438\u0448\u044c \u043c\u043b\u0430\u0434\u0448\u0438\u0435 48! \u0423\u043c\u043d\u043e\u0436\u0438\u043c \u043d\u0430\u0448\u0438 \u0437\u043d\u0430\u0447\u0435\u043d\u0438\u044f &#171;\u0441\u0442\u043e\u043b\u0431\u0438\u043a\u043e\u043c&#187; \u043a\u0430\u043a <strong>12-\u0431\u0438\u0442\u043d\u044b\u0435 \u0441\u043b\u043e\u0432\u0430<\/strong> (\u043f\u043e\u0441\u043a\u043e\u043b\u044c\u043a\u0443 16-\u0431\u0438\u0442\u043d\u044b\u0435 \u0432\u0441\u0435-\u0442\u0430\u043a\u0438 \u043f\u0440\u0438 \u0443\u043c\u043d\u043e\u0436\u0435\u043d\u0438\u0438 \u0432\u044b\u043b\u0435\u0437\u0430\u044e\u0442 \u0432 \u0437\u043d\u0430\u043a\u043e\u0432\u044b\u0439 \u0431\u0438\u0442) \u0441 \u043e\u0433\u0440\u0430\u043d\u0438\u0447\u0435\u043d\u0438\u0435\u043c \u0440\u0430\u0437\u0440\u044f\u0434\u043d\u043e\u0441\u0442\u0438:<\/p>\n<pre><code>         12 12 12 12 48 bit =  A  B  C  D         * E  F  G  H --------------------         |AH BH CH DH = A B C D * 0 0 0 H       AG|BG CG DG    = 0 B C D * 0 0 G 0    AF BF|CF DF       = 0 0 C D * 0 F 0 0 AE BE CE|DE          = 0 0 0 D * E 0 0 0<\/code><\/pre>\n<p>\u041e\u0441\u0442\u0430\u043b\u043e\u0441\u044c \u0442\u043e\u043b\u044c\u043a\u043e \u044d\u0442\u043e \u0432\u0441\u0435 \u0441\u043b\u043e\u0436\u0438\u0442\u044c, \u0434\u043e\u0431\u0430\u0432\u0438\u0442\u044c <strong>0x000b<\/strong>, \u043e\u0442\u0431\u0440\u043e\u0441\u0438\u0442\u044c \u043d\u0435\u043d\u0443\u0436\u043d\u044b\u0435 \u0441\u0442\u0430\u0440\u0448\u0438\u0435 \u0431\u0438\u0442\u044b \u0438 \u043f\u043e\u0434\u0435\u043b\u0438\u0442\u044c, \u0438 &#8212; \u0440\u0435\u0437\u0443\u043b\u044c\u0442\u0430\u0442 \u0432\u044b \u0443\u0436\u0435 \u0432\u0438\u0434\u0435\u043b\u0438 \u0432 \u0441\u0430\u043c\u043e\u043c \u043d\u0430\u0447\u0430\u043b\u0435 \u0441\u0442\u0430\u0442\u044c\u0438.<\/p>\n<\/div>\n<p> \u0441\u0441\u044b\u043b\u043a\u0430 \u043d\u0430 \u043e\u0440\u0438\u0433\u0438\u043d\u0430\u043b \u0441\u0442\u0430\u0442\u044c\u0438 <a href=\"https:\/\/habr.com\/ru\/company\/tensor\/blog\/547108\/\"> https:\/\/habr.com\/ru\/company\/tensor\/blog\/547108\/<\/a><br \/><\/br><\/br><\/p>\n","protected":false},"author":1,"featured_media":0,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"footnotes":""},"categories":[],"tags":[],"class_list":["post-319597","post","type-post","status-publish","format-standard","hentry"],"_links":{"self":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/319597","targetHints":{"allow":["GET"]}}],"collection":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcomments&post=319597"}],"version-history":[{"count":0,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=\/wp\/v2\/posts\/319597\/revisions"}],"wp:attachment":[{"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fmedia&parent=319597"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Fcategories&post=319597"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/savepearlharbor.com\/index.php?rest_route=%2Fwp%2Fv2%2Ftags&post=319597"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}