Чи існує функція для генерації випадкового int числа в C? Або мені доведеться використовувати сторонні бібліотеки?
srand
: навіщо називати це лише один раз .
Чи існує функція для генерації випадкового int числа в C? Або мені доведеться використовувати сторонні бібліотеки?
srand
: навіщо називати це лише один раз .
Відповіді:
Примітка . Не використовуйте
rand()
для безпеки. Якщо вам потрібен криптографічно захищений номер, дивіться замість цього відповідь .
#include <time.h>
#include <stdlib.h>
srand(time(NULL)); // Initialization, should only be called once.
int r = rand(); // Returns a pseudo-random integer between 0 and RAND_MAX.
Редагування : В Linux ви можете скористатися випадковим і srandom .
time()
змінюється лише раз на секунду. Якщо ви будете отримувати набір time()
для кожного дзвінка rand()
, ви отримаєте однакове значення для кожного дзвінка протягом однієї секунди. Але більша причина полягає в тому, що властивості rand()
та такі функції, як вони, відомі найкращим чином у випадку використання, коли вони висіваються рівно один раз на пробіг, а не на кожен виклик. Залежно від "випадковості" з неперевіреними або недоведеними властивостями призводить до неприємностей.
rand()
зазвичай є) посів насіння rand()
в кращому випадку не матиме жодного ефекту, а в гіршому випадку порушує відомі якості генератора. Це глибока тема. Почніть з читання Knuth Vol 2 Глава 3 про випадкові числа як найкращий вступ до математики та підводних каменів.
srand((unsigned int)time(NULL));
rand()
Функція <stdlib.h>
повертає псевдо-випадкове число між 0 і RAND_MAX
. Ви можете використовувати srand(unsigned int seed)
для встановлення насіння.
Це звичайна практика використовувати %
оператора спільно з, rand()
щоб отримати інший діапазон (хоча майте на увазі, що це дещо знімає рівномірність). Наприклад:
/* random int between 0 and 19 */
int r = rand() % 20;
Якщо ви насправді дбаєте про рівномірність, ви можете зробити щось подібне:
/* Returns an integer in the range [0, n).
*
* Uses rand(), and so is affected-by/affects the same seed.
*/
int randint(int n) {
if ((n - 1) == RAND_MAX) {
return rand();
} else {
// Supporting larger values for n would requires an even more
// elaborate implementation that combines multiple calls to rand()
assert (n <= RAND_MAX)
// Chop off all of the values that would cause skew...
int end = RAND_MAX / n; // truncate skew
assert (end > 0);
end *= n;
// ... and ignore results from rand() that fall above that limit.
// (Worst case the loop condition should succeed 50% of the time,
// so we can expect to bail out of this loop pretty quickly.)
int r;
while ((r = rand()) >= end);
return r % n;
}
}
%
Оператор модуля. Це дає залишок від ділення без остачі, так що x % n
завжди буде давати вам номер між 0
і n - 1
( до тих пір , як x
і n
обидва позитивні). Якщо ви все-таки вважаєте це заплутаним, спробуйте написати програму, яка i
нараховує від 0 до 100, і роздрукує i % n
певну n
частину вашого вибору менше 100.
Як розглянуто, як безпечно генерувати випадкові числа на різних мовах програмування , вам потрібно зробити одне з наступних:
randombytes
API/dev/urandom
, ні /dev/random
. Не OpenSSL (або інші PRNG).Наприклад:
#include "sodium.h"
int foo()
{
char myString[32];
uint32_t myInt;
if (sodium_init() < 0) {
/* panic! the library couldn't be initialized, it is not safe to use */
return 1;
}
/* myString will be an array of 32 random bytes, not null-terminated */
randombytes_buf(myString, 32);
/* myInt will be a random number between 0 and 9 */
myInt = randombytes_uniform(10);
}
randombytes_uniform()
є криптографічно захищеним та неупередженим.
sodium_init()
в якийсь момент. Не турбуйтеся про RNG, він використовує ядро.
sodium_init()
хоча це не обов'язково є частиною мого прикладу, оскільки це важлива деталь.
Давайте пройдемося через це. Спочатку ми використовуємо функцію srand () для висіву рандомізатора. В основному комп'ютер може генерувати випадкові числа на основі числа, яке подається на srand (). Якби ви дали одне і те ж значення насіння, то кожного разу будуть генеруватися однакові випадкові числа.
Тому нам доведеться викласти рандомізатор зі значенням, яке завжди змінюється. Ми робимо це, подаючи йому значення поточного часу за допомогою функції time ().
Тепер, коли ми викликаємо rand (), кожного разу буде створюватися нове випадкове число.
#include <stdio.h>
int random_number(int min_num, int max_num);
int main(void)
{
printf("Min : 1 Max : 40 %d\n", random_number(1,40));
printf("Min : 100 Max : 1000 %d\n",random_number(100,1000));
return 0;
}
int random_number(int min_num, int max_num)
{
int result = 0, low_num = 0, hi_num = 0;
if (min_num < max_num)
{
low_num = min_num;
hi_num = max_num + 1; // include max_num in output
} else {
low_num = max_num + 1; // include max_num in output
hi_num = min_num;
}
srand(time(NULL));
result = (rand() % (hi_num - low_num)) + low_num;
return result;
}
else{ low_num=max_num; hi_num=min_num+1;
2) не вдається, коли hi_num - low_num > INT_MAX
. 3) Опускає значення в рідкісній ситуації INT_MAX > hi_num - low_num > RAND_MAX
.
hi_num = max_num + 1;
не вистачає захисту від переливу.
Якщо вам потрібні псевдо випадкові числа кращої якості, ніж те, що stdlib
передбачено, перегляньте Mersenne Twister . Це теж швидше. Зразкових реалізацій багато, наприклад, тут .
Стандартна функція С є rand()
. Це досить добре, щоб розібрати картки для пасьянсу, але це жахливо. Багато реалізацій rand()
циклу через короткий список чисел, а низькі біти мають коротші цикли. Те, як називають деякі програми rand()
, жахливе, і обчислити хороший насіннєвий прохід srand()
важко.
Найкращий спосіб генерувати випадкові числа в C - це використання сторонньої бібліотеки на зразок OpenSSL. Наприклад,
#include <stdint.h>
#include <stdio.h>
#include <stdlib.h>
#include <openssl/rand.h>
/* Random integer in [0, limit) */
unsigned int random_uint(unsigned int limit) {
union {
unsigned int i;
unsigned char c[sizeof(unsigned int)];
} u;
do {
if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
} while (u.i < (-limit % limit)); /* u.i < (2**size % limit) */
return u.i % limit;
}
/* Random double in [0.0, 1.0) */
double random_double() {
union {
uint64_t i;
unsigned char c[sizeof(uint64_t)];
} u;
if (!RAND_bytes(u.c, sizeof(u.c))) {
fprintf(stderr, "Can't get random bytes!\n");
exit(1);
}
/* 53 bits / 2**53 */
return (u.i >> 11) * (1.0/9007199254740992.0);
}
int main() {
printf("Dice: %d\n", (int)(random_uint(6) + 1));
printf("Double: %f\n", random_double());
return 0;
}
Чому так багато коду? Інші мови, такі як Java і Ruby, мають функції для випадкових цілих чисел або плавців. OpenSSL видає лише випадкові байти, тому я намагаюся імітувати, як Java або Ruby перетворювали б їх на цілі чи плавці.
Для цілих чисел ми хочемо уникнути зміщення модуля . Припустимо, ми отримали від випадкових чотиризначних цілих чисел rand() % 10000
, але rand()
можемо повернути лише 0 до 32767 (як це робиться в Microsoft Windows). Кожне число від 0 до 2767 відображатиметься частіше, ніж кожне число від 2768 до 9999. Щоб видалити зміщення, ми можемо повторити спробуrand()
поки значення нижче 2768, оскільки значення 30000 від 2768 до 32767 відображаються рівномірно на значення 10000 від 0 до 9999.
Для плавців ми хочемо 53 випадкових біта, тому що double
тримає 53 біта точності (якщо припустити, що це IEEE подвійний). Якщо ми використовуємо більше 53 біт, ми отримуємо округлення зміщення. Деякі програмісти записують такий код, як rand() / (double)RAND_MAX
, але rand()
можуть повернути лише 31 біт або лише 15 біт у Windows.
RAND_bytes()
Насіння OpenSSL , можливо, читаючи /dev/urandom
в Linux. Якщо нам потрібно багато випадкових чисел, було б занадто повільно їх читати /dev/urandom
, тому що вони повинні бути скопійовані з ядра. Швидше дозволити OpenSSL генерувати більше випадкових чисел із насіння.
Більше про випадкові числа:
srand()
. Він змішує біти поточного часу, ідентифікатор процесу та деякі покажчики, якщо він не може прочитати /dev/urandom
.float
/ double
, тож я уточнив питання, щоб дотримуватися int
цифр, щоб не зробити його занадто широким. Є й інші питання C, які стосуються конкретно float
/ double
випадкових значень, тому ви, можливо, захочете перевстановити свою другу половину своєї відповіді на такі питання, як stackoverflow.com/questions/13408990/…
Якщо ваша система підтримує arc4random
сімейство функцій, я б рекомендував використовувати їх замість стандартної rand
функції.
arc4random
Сімейство включає в себе:
uint32_t arc4random(void)
void arc4random_buf(void *buf, size_t bytes)
uint32_t arc4random_uniform(uint32_t limit)
void arc4random_stir(void)
void arc4random_addrandom(unsigned char *dat, int datlen)
arc4random
повертає випадкове 32-бітне ціле число, не підписане
arc4random_buf
додає випадковий вміст у його параметр buf : void *
. Кількість вмісту визначається bytes : size_t
параметром.
arc4random_uniform
повертає випадкове 32-бітове непідписане ціле число, яке слідує правилу: 0 <= arc4random_uniform(limit) < limit
де лімітом є також непідписане 32-бітове ціле число.
arc4random_stir
зчитує дані /dev/urandom
і передає їх, arc4random_addrandom
щоб додатково рандомізувати свій внутрішній пул випадкових чисел.
arc4random_addrandom
використовується arc4random_stir
для заповнення внутрішнього пулу випадкових чисел відповідно до переданих йому даних.
Якщо у вас немає цих функцій, але ви перебуваєте на Unix, ви можете використовувати цей код:
/* This is C, not C++ */
#include <sys/types.h>
#include <sys/stat.h>
#include <fcntl.h>
#include <errno.h>
#include <unistd.h>
#include <stdlib.h> /* exit */
#include <stdio.h> /* printf */
int urandom_fd = -2;
void urandom_init() {
urandom_fd = open("/dev/urandom", O_RDONLY);
if (urandom_fd == -1) {
int errsv = urandom_fd;
printf("Error opening [/dev/urandom]: %i\n", errsv);
exit(1);
}
}
unsigned long urandom() {
unsigned long buf_impl;
unsigned long *buf = &buf_impl;
if (urandom_fd == -2) {
urandom_init();
}
/* Read 4 bytes, or 32 bits into *buf, which points to buf_impl */
read(urandom_fd, buf, sizeof(long));
return buf_impl;
}
urandom_init
Функція відкриває /dev/urandom
пристрій, і поміщає дескриптор файлу в urandom_fd
.
urandom
Функція в основному така ж , як заклик до rand
, за винятком більш безпечним, і вона повертаєlong
(легко змінюваний).
Однак це /dev/urandom
може бути трохи повільним, тому рекомендується використовувати його як насіння для іншого генератора випадкових чисел.
Якщо ваша система не має /dev/urandom
, але дійсно є /dev/random
або подібний файл, то ви можете просто змінити шлях , пройдений до open
в urandom_init
. Виклики та API, які використовуються urandom_init
та urandom
є (я вважаю) сумісними з POSIX, і як такі, повинні працювати на більшості, якщо не на всіх сумісних з POSIX системах.
Примітки. Прочитання від /dev/urandom
НЕ блокується, якщо недоступна ентропія, тому значення, створені за таких обставин, можуть бути криптографічно незахищеними. Якщо ви переживаєте з цього приводу, тоді використовуйте /dev/random
, яке завжди блокується, якщо недостатня ентропія.
Якщо ви перебуваєте в іншій системі (наприклад, Windows), використовуйте rand
або якийсь внутрішній API, що не залежить від платформи, залежний від платформи Windows.
Обгортка функції для urandom
, rand
або arc4random
викликів:
#define RAND_IMPL /* urandom(see large code block) | rand | arc4random */
int myRandom(int bottom, int top){
return (RAND_IMPL() % (top - bottom)) + bottom;
}
STL не існує для C. Ви повинні зателефонувати rand
, або ще краще, random
. Вони задекларовані в стандартному заголовку бібліотеки stdlib.h
. rand
є POSIX,random
є функцією специфікації BSD.
Різниця між rand
і random
полягає в тому, що random
повертає набагато більш зручне 32-бітове випадкове число і, rand
як правило, повертає 16-бітове число. Настанови BSD показують, що нижчі біти rand
циклічні та передбачувані, тому rand
потенційно марні для невеликої кількості.
extern int rand(void);
і extern void srand(unsigned int);
.
Подивіться на ISAAC (непрямий, зсув, накопичення, додавання та підрахунок). Він рівномірно розподілений і має середню довжину циклу 2 ^ 8295.
Це хороший спосіб отримати випадкове число між двома обраними вами числами.
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
#define randnum(min, max) \
((rand() % (int)(((max) + 1) - (min))) + (min))
int main()
{
srand(time(NULL));
printf("%d\n", randnum(1, 70));
}
Вихід перший раз: 39
Виведіть другий раз: 61
Виведіть третій раз: 65
Ви можете змінювати значення після того, randnum
як ви обрали будь-які числа, і це створить випадкове число для вас між цими двома числами.
Ви хочете використовувати rand()
. Примітка ( ДУЖЕ ВАЖЛИВО ): не забудьте встановити насіння для функції rand. Якщо цього не зробити, ваші випадкові числа не є справді випадковими . Це дуже, дуже, дуже важливо. На щастя, зазвичай ви можете використовувати деяку комбінацію таймера системних кліщів та дати, щоб отримати гарне насіння.
FWIW, відповідь полягає в тому, що так, є stdlib.h
функція, яка називається rand
; ця функція налаштована насамперед на швидкість і розподіл, а не на непередбачуваність. Майже всі вбудовані випадкові функції для різних мов та фреймворків використовують цю функцію за замовчуванням. Існують також "криптографічні" генератори випадкових чисел, які набагато менш передбачувані, але працюють набагато повільніше. Вони повинні використовуватися в будь-якому застосуванні, пов'язаному з безпекою.
Сподіваємось, це трохи випадковіше, ніж просто використання srand(time(NULL))
.
#include <time.h>
#include <stdio.h>
#include <stdlib.h>
int main(int argc, char **argv)
{
srand((unsigned int)**main + (unsigned int)&argc + (unsigned int)time(NULL));
srand(rand());
for (int i = 0; i < 10; i++)
printf("%d\n", rand());
}
Ну, STL - це C ++, а не C, тому я не знаю, що ви хочете. Якщо ви хочете C, однак, є rand()
і srand()
функції:
int rand(void);
void srand(unsigned seed);
Вони обидва є частиною ANSI C. Є також random()
функція:
long random(void);
Але наскільки я можу сказати, random()
це не стандартний ANSI C. Стороння бібліотека може бути не поганою ідеєю, але все залежить від того, наскільки випадковим є число, яке вам потрібно створити.
C Програма для генерації випадкових чисел між 9 і 50
#include <time.h>
#include <stdlib.h>
int main()
{
srand(time(NULL));
int lowerLimit = 10, upperLimit = 50;
int r = lowerLimit + rand() % (upperLimit - lowerLimit);
printf("%d", r);
}
Взагалі ми можемо генерувати випадкове число між нижчим і нижчим лімітом-1
тобто нижній ліміт включений або скажіть r ∈ [нижній ліміт, верхній ліміт)
rand()
є найзручнішим способом генерації випадкових чисел.
Ви також можете зловити випадкове число з будь-якої інтернет-служби, наприклад random.org.
#include <stdio.h>
#include <stdlib.h>
void main()
{
int visited[100];
int randValue, a, b, vindex = 0;
randValue = (rand() % 100) + 1;
while (vindex < 100) {
for (b = 0; b < vindex; b++) {
if (visited[b] == randValue) {
randValue = (rand() % 100) + 1;
b = 0;
}
}
visited[vindex++] = randValue;
}
for (a = 0; a < 100; a++)
printf("%d ", visited[a]);
}
#include <stdio.h>
#include <dos.h>
int random(int range);
int main(void)
{
printf("%d", random(10));
return 0;
}
int random(int range)
{
struct time t;
int r;
gettime(&t);
r = t.ti_sec % range;
return r;
}
У сучасних процесорах x86_64 ви можете використовувати апаратний генератор випадкових чисел через _rdrand64_step()
Приклад коду:
#include <immintrin.h>
uint64_t randVal;
if(!_rdrand64_step(&randVal)) {
// Report an error here: random number generation has failed!
}
// If no error occured, randVal contains a random 64-bit number
#include<stdio.h>
#include<stdlib.h>
#include<time.h>
//generate number in range [min,max)
int random(int min, int max){
int number = min + rand() % (max - min);
return number;
}
//Driver code
int main(){
srand(time(NULL));
for(int i = 1; i <= 10; i++){
printf("%d\t", random(10, 100));
}
return 0;
}
Почувши гарне пояснення того, чому використовувати rand()
для отримання рівномірно розподілених випадкових чисел у заданому діапазоні є поганою ідеєю, я вирішив поглянути на те, наскільки насправді є вихідний результат. Мій тестовий випадок був справедливим метанням кісток. Ось код C:
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
int main(int argc, char *argv[])
{
int i;
int dice[6];
for (i = 0; i < 6; i++)
dice[i] = 0;
srand(time(NULL));
const int TOTAL = 10000000;
for (i = 0; i < TOTAL; i++)
dice[(rand() % 6)] += 1;
double pers = 0.0, tpers = 0.0;
for (i = 0; i < 6; i++) {
pers = (dice[i] * 100.0) / TOTAL;
printf("\t%1d %5.2f%%\n", dice[i], pers);
tpers += pers;
}
printf("\ttotal: %6.2f%%\n", tpers);
}
і ось його результат:
$ gcc -o t3 t3.c
$ ./t3
1666598 16.67%
1668630 16.69%
1667682 16.68%
1666049 16.66%
1665948 16.66%
1665093 16.65%
total: 100.00%
$ ./t3
1667634 16.68%
1665914 16.66%
1665542 16.66%
1667828 16.68%
1663649 16.64%
1669433 16.69%
total: 100.00%
Я не знаю, наскільки рівномірними вам потрібні випадкові числа, але вищезазначене виглядає досить рівномірним для більшості потреб.
Редагувати: було б корисно ініціалізувати PRNG з чимось кращим, ніж time(NULL)
.
У моїй недавній програмі у мене виник серйозна проблема з генератором псевдовипадкових чисел: я повторно називав свою програму C через сценарій pyhton, і я використовував як насіння наступний код:
srand(time(NULL))
Однак, оскільки:
man srand
);time
кожен раз буде повертати одне і те ж значення.Моя програма генерувала однакову послідовність чисел. Ви можете зробити 3 речі для вирішення цієї проблеми:
змішати час виводу з іншою інформацією, що змінюється на прогонах (у моєму додатку назва виводу):
srand(time(NULL) | getHashOfString(outputName))
Я використовував djb2 як свою хеш-функцію.
Збільшити дозвіл часу. На моїй платформі clock_gettime
був доступний, тому я використовую її:
#include<time.h>
struct timespec nanos;
clock_gettime(CLOCK_MONOTONIC, &nanos)
srand(nanos.tv_nsec);
Використовуйте обидва способи разом:
#include<time.h>
struct timespec nanos;
clock_gettime(CLOCK_MONOTONIC, &nanos)
srand(nanos.tv_nsec | getHashOfString(outputName));
Варіант 3 забезпечує вам (наскільки я знаю) найкращу випадковість насіння, але це може створити різницю лише при дуже швидкому застосуванні. На мою думку, варіант 2 - це безпечна ставка.
rand()
не слід використовувати для криптографічних даних, я згоден. Принаймні для мене моя програма не передбачала криптографічних даних, тому для мене це було нормально даним методом.
Незважаючи на всі пропозиції людей rand()
тут, ви не хочете користуватися, rand()
якщо вам не доведеться! Випадкові числа, які rand()
виробляють, часто дуже погані. Процитуйте зі сторінки чоловіка Linux:
У версіях
rand()
іsrand()
в бібліотеці Linux C використовується той же генератор випадкових чисел, щоrandom(3)
іsrandom(3)
, тому біти нижчого порядку повинні бути такими ж випадковими, як і біти вищого порядку. Однак у старих реалізаціях rand () та в поточних реалізаціях в різних системах біти нижчого порядку набагато менш випадкові, ніж біти вищого порядку . Не використовуйте цю функцію в додатках, призначених для переносності, коли потрібна хороша випадковість. ( Використовуйтеrandom(3)
замість цього. )
Що стосується портативності, random()
вона також визначається стандартом POSIX вже досить давно. rand()
старше, він з'явився вже в першій специфікації POSIX.1 (IEEE Std 1003.1-1988), тоді як random()
вперше з'явився в POSIX.1-2001 (IEEE Std 1003.1-2001), але поточний стандарт POSIX вже є POSIX.1-2008 (IEEE Std 1003.1-2008), який отримав оновлення лише рік тому (IEEE Std 1003.1-2008, Edition 2016). Тож я б вважав random()
дуже портативним.
POSIX.1-2001 також запровадив lrand48()
і mrand48()
функції, дивіться тут :
Це сімейство функцій повинно генерувати псевдовипадкові числа, використовуючи лінійний конгрурентний алгоритм та 48-бітну цілу арифметику.
І досить хорошим псевдо випадковим джерелом є arc4random()
функція, яка доступна у багатьох системах. Не входить до жодного офіційного стандарту, що з'явився в BSD близько 1997 року, але його можна знайти в таких системах, як Linux та macOS / iOS.
random()
не існує в Windows.
rand()
цього вимагає і стандарт C. Для всього іншого вам потрібно спеціальне рішення лише для Windows, як і зазвичай. #ifdef _WIN32
- це фраза, яку ви бачите найчастіше в кросплатформенному коді, який хоче підтримувати Windows, а зазвичай є одне рішення, яке працює з усіма системами, і таке, яке потрібно лише для Windows.
Для додатків Linux C:
Це мій перероблений код з відповіді вище, яка відповідає моїй практиці з кодом С і повертає випадковий буфер будь-якого розміру (з належними кодами повернення тощо). Обов’язково телефонуйте urandom_open()
один раз на початку програми.
int gUrandomFd = -1;
int urandom_open(void)
{
if (gUrandomFd == -1) {
gUrandomFd = open("/dev/urandom", O_RDONLY);
}
if (gUrandomFd == -1) {
fprintf(stderr, "Error opening /dev/urandom: errno [%d], strerrer [%s]\n",
errno, strerror(errno));
return -1;
} else {
return 0;
}
}
void urandom_close(void)
{
close(gUrandomFd);
gUrandomFd = -1;
}
//
// This link essentially validates the merits of /dev/urandom:
// http://sockpuppet.org/blog/2014/02/25/safely-generate-random-numbers/
//
int getRandomBuffer(uint8_t *buf, int size)
{
int ret = 0; // Return value
if (gUrandomFd == -1) {
fprintf(stderr, "Urandom (/dev/urandom) file not open\n");
return -1;
}
ret = read(gUrandomFd, buf, size);
if (ret != size) {
fprintf(stderr, "Only read [%d] bytes, expected [%d]\n",
ret, size);
return -1;
} else {
return 0;
}
}
Моє мінімалістичне рішення повинно працювати для випадкових чисел у діапазоні [min, max)
. Використовуйте srand(time(NULL))
перед викликом функції.
int range_rand(int min_num, int max_num) {
if (min_num >= max_num) {
fprintf(stderr, "min_num is greater or equal than max_num!\n");
}
return min_num + (rand() % (max_num - min_num));
}
Спробуйте це, я зібрав це з деяких понять, на які вже згадувалося вище:
/*
Uses the srand() function to seed the random number generator based on time value,
then returns an integer in the range 1 to max. Call this with random(n) where n is an integer, and you get an integer as a return value.
*/
int random(int max) {
srand((unsigned) time(NULL));
return (rand() % max) + 1;
}
srand()
кожен раз, коли ви хочете зателефонувати rand()
- це жахлива ідея. Оскільки time()
зазвичай повертає значення за секунди, швидко викликаючи цю функцію, повернеться те саме "випадкове" значення.
random()
функцією Unix .