درک آمار و احتمال برای برخی ممکن است ساده باشد ولی برای بسیاری از ما، موضوعی دشوار است. استفاده از شبیهسازی به ما کمک میکند تا برخی از رمز و رازهای آمار و احتمال برطرف شوند. خوشبختانه، تولید یک دنباله شبهتصادفی (Pseudo random) یا دنباله یکنواخت ساده است: یک دستور ساده در متلب (MATLAB) یا نرمافزار R و یا پایتون این کار را انجام میدهد.
در این مقاله، ابتدا مروری بر قضیه حد مرکزی (Central Limit Theorem – CLT) خواهیم داشت و سپس مفاهیم مرتبط با دنبالههای تصادفی با توزیع یکنواخت (Uniform) و گوسین (Gaussian) و شبیهسازی آنها در نرمافزار متلب و R را برای اثبات شهودی قضیه حد مرکزی، بررسی میکنیم.
در بخش متلب، ابتدا یک دنباله گوسین تولید کرده و واریانس آن را محاسبه میکنیم. سپس هیستوگرام و تابع چگالی احتمال (PDF) آن را رسم میکنیم. در ادامه، رخداد انداختن یک تاس را برای نمایش توزیع یکنواخت، شبیهسازی میکنیم. این کار را برای دو تاس و در نهایت برای اثبات قضیه حد مرکزی، برای حالت چندین تاس، مجموع نتایج را برای دستیابی به توزیع گوسین تقریبی، محاسبه میکنیم.
در بخش R، تولید متغیرهای تصادفی یکنواخت، محاسبه میانگین آنها و در نهایت تابع توزیع احتمال این میانگینها بررسی و رسم میشود و از این طریق قضیه حد مرکزی به صورت شهودی اثبات میشود.
آشنایی با قضیه حد مرکزی
قضیه حد مرکزی، یکی از مفاهیم اساسی در آمار و احتمال است. طبق این قضیه، برای یک مجموعه بزرگ از نمونهها، توزیع میانگین نمونهها فارغ از اینکه توزیع اصلی داده چه توزیعی باشد، به یک توزیع نرمال میل میکند. به زبان ساده، زمانیکه متغیرهای تصادفی مستقل با هم جمع میشوند، جمع استاندارد شده آنها با افزایش تعداد متغیرها، تمایل دارد تا تحت شرایط مشخصی از یک توزیع نرمال پیروی کند.
توزیع میانگین نمونهها: قضیه CLT این اطمینان را میدهد که میانگینهای متغیرهای تصادفی مستقل با تعداد به اندازه کافی بزرگ، از یک توزیع نرمال پیروی میکند.
اندازه نمونه: هر چه اندازه نمونهها بیشتر باشد، توزیع میانگین نمونهها به نرمال نردیکتر است.
توزیع اصلی: توزیع اصلی نمونهها لازم نیست حتما نرمال باشد و میتواند هر توزیعی باشد، مثلا یکنواخت، دوجملهای یا نمایی.
بخش اول: شبیهسازی متلب
تولید یک دنباله گوسین
روشهای متعددی برای تولید دنبالههای شبهتصادفی گوسین وجود دارد. دنبالههای گوسین توسط میانگین \( \mu \) و انحراف معیار \( \sigma \) مشخص میشوند. در متلب، تابع randn یک دنباله گوسین استاندارد با میانگین \( \mu = 0 \) و انحراف معیار \( \sigma =1 \) تولید میکند. حرف n در randn اول کلمه normal است. کد متلب برای تولید دنباله گوسین استاندارد به شرح زیر است:
rng(0) % set random number generator seed
N = 10000; % number of samples in sequence
sigma = 1.0; % standard deviation
x = sigma*randn(1,N); % Gaussian sequence
سید (seed) مولد اعداد تصادفی میتواند هر عدد مثبتی باشد، حتی صفر. دنباله \( x \) در شکل یک رسم شده است و اکثر نمونهها در بازه \( +/- 3 \sigma \) قرار دارد. در حقیقت، در حدود 99.7% نمونهها در این بازه قرار دارند.
برای هر دنباله، میانگین و واریانس را به شکل زیر میتوان محاسبه کرد:
$$ \mu = \frac{1}{N} \sum_{n=0}^{N-1} x(n) $$
$$ \text{variance} = \sigma^2 = \frac{1}{N} \sum_{n=0}^{N-1} [x(n)-\mu]^2, \ \ \ \ N > 100 $$
که در آن واریانس \( \sigma \) به صورت ریشه دوم واریانس تعریف میشود (دقت کنید که برای \( N<100 \) معمولا مخرج را \( N-1 \) به جای \( N \) در نظر میگیرند که منجر به تخمین بدون بایاس (unbiased) واریانس میشود. در دنباله ما، \( \sigma = 1 \) است و در نتیجه، واریانس \( \sigma^2 = 1\) است. با توجه به اینکه \( \mu = 0 \)، محاسبات به شرح زیر است:
variance = sum(x.^2)/N % variance of sequence
variance = 0.9829
واریانس محاسبه شده دنباله دقیقا یک نیست. به عبارت دیگر، به طور دقیق برابر با واریانس فرآنید گوسین مورد نظر نیست. این مساله، ویژگی دنبالهها در دنیای واقعی است که به نویز آماری موسوم است. برای دنباله طولانیتر، واریانس به مقدار 1 نزدیکتر خواهد بود. برای \( \mu = 0 \)، واریانس برابر است با:
$$ \sigma^2 = \frac{1}{N} \sum_{n=0}^{N-1} x(n)^2 $$
اگر فرض کنیم متغیر \( x \) از جنس ولتاژ است و مقاومت یک اهم در مسیر آن در نظر گرفته شود، \( x(n)^2 \) توان لحظهای نمونه n-ام است و \( \sigma ^2 \) برابر با توان متوسط دنباله با میانگین صفر بر حسب وات است. این تفسیر برای تولید سیگنالهای زمان-گسسته با نسبت سیگنال به نویز (S/N) مشخص در شبیهسازیها، قابل استفاده است.
شکل 1- دنباله گوسین x با طول 10000
هیستوگرام یک دنباله
در شکل زیر (سمت چپ) همان دنباله گوسین را میبینیم. در سمت راست نیز نمودار هیستوگرام این دنباله مشاهده میشود که در محور عمودی با شکل سمت چپ اشتراک دارد. میلههای افقی در این شکل، تعداد نمونههایی که در محدوده مشخصی از مقادیر قرار میگیرند را نشان میدهد. این اعداد، تعداد دسته (bin count) یا همان تعداد نام دارند. واضح است که بیشترین تعداد در مرکز نمودار، \( x=0 \)، رخ داده است و تعداد برای مقادیر \( |x| > 3 \) خیلی کم است.
شکل 2- دنباله تصادفی گوسین \( x \) (سمت چپ) و هیستوگرام آن (سمت راست)
محاسبه هیستوگرام دنباله گوسین
میخواهیم هیستوگرام یک دنباله گوسین با طول \( N=100e3 \) را ایجاد کنیم. این هیستوگرام در شکل 3 نمایش داده شده است که در آن \( x \) به محور افقی اختصاص داده شده است و تعداد به محور عمودی
مقادیر دنباله \( x \)، پیوسته هستند که به دستهها یا قسمتهای با عرض 0.25 تقسیم میشوند. برای مثال، یک قسمت به مرکز صفر است که تعداد دسته آن 9949 است. استفاده از دستههای با عرض کمتر، رزولوشن افقی نمودار را افزایش میدهد ولی منجر به تغییرات ناخواسته در تعداد دستهها میشود.
کد متلب زیر، شکل هیستوگرام در پایین را تولید میکند.
rng(0) % set random number gererator seed
N = 100E3; % number of samples in sequence
sigma = 1.0; % standard deviation
x = sigma*randn(1,N); % Gaussian sequence
pdf_plot(x) % plot histogram and pdf

شکل 3- هیستوگرام دنباله گوسین با \( \sigma=1, N=100e3 \)
تابع توزیع احتمال (PDF) یک دنباله
در شکل بالا، مجموع تمام مقادیر دستهها برابر با تعداد کل نمونههای دنباله، \( N \)، است:
$$ \sum_{i=1}^{nbins} counts(i)=N $$
که در آن \( i \) شماره دسته و nbins تعداد کل دستهها است. در معادله بالا، دستههای تعریف شده برای مقادیر دنباله باید شامل کل مقادیر باشد. برای مثال، اگر این دستهها بازه -2 تا 2 را پوشش دهند، برخی مقادیر \( x \) از این شمارش مستثنی میشوند و جمع مقادیر دستهها، کمتر از \( N \) خواهد شد. همچنین میتوان نوشت:
$$ \frac{1}{N}\sum_{i=1}^{nbins} counts(i)=1 $$
حال میتوان، تابع توزیع احتمال تخمینی دنباله بالا را به شکل زیر نوشت:
$$ pdf(i)=\frac{counts(i)}{N.w} $$
که در آن \( w \) عرض دسته در هیستوگرام است. سپس داریم:
$$ \sum_{i=1}^{nbins} pdf(i).w=1 $$
که \( pdf(i).w \) احتمال تخمینی دسته i-ام است و جمع همه این احتمالها نیز برابر با یک است.
تابع PDF یک دنباله گوسین
کد متلب که در بالا برای تولید هیستوگرام استفاده شد، میتواند تابع PDF دنباله گوسین را نیز محاسبه و رسم کند. شکل زیر این نمودار را نشان میدهد. در این شکل هر میله دارای مساحت \( w.pdf(i) \) است و مجموع آنها نیز یک میشود.
آیا این تخمین تابع توزیع احتمال، با مقدار واقعی آن توافق دارد؟ همانطور که میدانید، تابع توزیع احتمال یک دنباله گوسین به صورت زیر است:
$$ p(x)=\frac{1}{\sigma \sqrt{2 \pi}}e^{-(x-\mu)^2/2\sigma^2} $$

شکل 4- PDF دنباله گوسین با \( \sigma=1, N = 100e3 \)
در مثال ما، \( \sigma=1, \mu=0 \) است. در این حالت، نمودار PDF واقعی به صورت نمودار قرمز رنگ در شکل زیر روی هیستوگرام بدست آمده، رسم شده است.
شکل 5- PDF دنباله گوسین به همراه مقدار واقعی آن (رنگ قرمز)
تا اینجا در تمام دنبالهها، \( \sigma=1 \) بوده است. اگر از مقدار \( \sigma=0.5 \) استفاده کنیم، اندازه دامنه \( x(n) \) با ضریب 2 افزایش مییابد. در شکل زیر، تابع چگالی احتمال برای \( N=100e3 \) رسم شده است. اندازه دامنه بیشتر با محدوده باریکتر مقادیر pdf کاملا در شکل مشهود است.
شکل 6- pdf دنباله گوسین با \( \sigma=0.5, N=100e3 \)
در نهایت، فرض کنید که در دنباله گوسین، \( \sigma=1 \) ولی \( N=1000 \) است که بسیار کوتاهتر از موارد بالا با طول \( N=100e3 \) است. Pdf حاصل در شکل زیر نمایش داده شده است. نویز بیشتر در Pdf واضح است که در بخشهای جانبی pdf شدیدتر است. به دستههای خالی به مرکز \( x=-2.75 \) و \( x=3.25 \) نیز دقت کنید.
شکل 7- pdf دنباله گوسین با \( \sigma=1, N=1000\)
توزیع احتمال یکنواخت: پرتاب تاس
دنباله حاصل از چندین بار پرتاب تاس دارای توزیع احتمال یکنواخت است که در ادامه نشان داده خواهد شد. تا کنون از دنباله با مقدار \( x \) پیوسته استفاده کردیم اما نتایج حاصل از پرتاب تاس شامل مقادیر گسسته \( x=1,2,…,6 \) میشود. احتمال وقوع یک مقدار خاص \( x \) در \( N \) بار پرتاب تاس تقریبا برابر با تعداد رخداد مورد نظر تقسیم بر تعداد کل \( N \) است. تابع جرم احتمال تخمینی (PMF) یک دنباله با مقادیر گسسته برابر است با:
$$ pmf(i)=\frac{counts(i)}{N} $$
با فرض اینکه جمع تعداد برابر با \( N \) است، داریم:
$$ \sum_{i=1}^{nbins} pmf(i) = 1 $$
کد متلب زیر، پرتاب یک تاس را شبیهسازی کرده و تابع PMF را رسم میکند. تابع randi یک دنباله با توزیع یکنواخت در بازه [16] تولید میکند. هیستوگرام دنباله محاسبه و در نهایت تابع PMF رسم شده است.
rng(0) % set random number gererator seed
N = 10000; % number of die rolls
die = randi(6,1,N); % vector of integers over [1 6]
edges= .5:1:6.5; % edges of histogram bins
counts = histcounts(die,edges); % vector of histogram counts
pmf = counts/N; % pmf vector from Equation 9
% plot PMF
x= 1:6; % horizontal axis of pmf
bar(x,pmf,.05)
xlabel(‘die value’),ylabel(‘probability’)
متغیر die شامل مقادیر پرتابهای تاس است. 16 مقدار اول آن به شرح زیر است:
5 6 1 6 4 1 2 4 6 6 1 6 6 3 5 1
تابع PMF در شکل زیر نشان داده شده است که هر رخداد احتمالی برابر با \( 1/6=0.1667 \) دارد.
شکل 8- تابع PMF یکنواخت برای پرتاب یک تاس به تعداد 1000 بار
جمع دنبالهها – پرتاب دو تاس
نتیجه پرتاب دو تاس برابر با جمع مقادیر تاسها است. اگر دو تاس را چند بار پرتاب کنیم، دنباله تصادفی حاصل، جمع دو دنباله تصادفی هر مقدار تاس آمده است. در زیر، کد متلب برای محاسبه نتیجه پرتاب دو تاس آمده است. دقت کنید که دنبالههای die1,die2 مستقل هستند.
rng(0) % set random number gererator seed
N = 10000; % number of dice rolls
die1 = randi(6,1,N); % vector of die 1 integer values
die2 = randi(6,1,N); % vector of die 2 integer values
y = die1 + die2; % sum of the dice values
16 مقدار اول متغیر \( y \) در کد بالا به شرح زیر است:
6 12 7 9 7 2 8 5 8 8 2 7 11 6 8 3
تابع PMF متغیر \( y \) در شکل زیر آمده است. احتمالها بین 1/36 (مقدار 2 یا 12) و 6/36 (مقدار 7) است. میانگین و واریانس \( y \) عبارت است از:
mu =7.0018 variance =5.7422
انحراف معیار برابر با جذر واریانس است: \( \sigma=2.3963 \)
شکل 9- تابع PMF پرتاب دو تاس با هم برای N=10000
بررسی قضیه حد مرکزی
اگر 5 تاس پرتاب شوند و مجموع مقادیر آنها را محاسبه کنیم، با چه رخدادی مواجه میشویم؟ کد متلب برای این حالت در ادامه آمده است. این مجموع بین 5 تا 30 تغییر میکند. تابع PMF در شکل 10 نمایش داده شده است و به نظر میرسد که دارای توزیع گوسین است.
% PMF for throwing 5 dice
clear
rng(0) % set random number gererator seed
N = 100E3; % number of dice rolls
D = randi(6,5,N); % Matrix with 5 independent rows of die values
y = sum(D); % sum rows of matrix to get sum of dice values
% mean and variance of y
mu = sum(y)/N
variance = sum((y – mu).^2)/N
edges = 4.5:1:30.5; % edges of histogram bins
counts = histcounts(y,edges); % vector of histogram counts
pmf = counts/N; % pmf vector from Equation 9
% compute gaussian function probability p
x = 5:30; % horizontal axis of pdf
sigma = sqrt(variance);
% Gaussian PDF formula
p = 1/(sigma*sqrt(2*pi)) * exp(-(x – mu).^2/(2*sigma^2));
% plot PMF of y (bars) and Gaussian PDF (solid line)
bar(x,pmf,.2),hold on
plot(x,p,’linewidth’,2),hold off
xlabel(‘sum of dice values’),ylabel(‘probability’)
با محاسبه میانگین و واریانس تابع PMF داریم:
mu = 17.5020
variance = 14.4949
اگر PDF یک توزیع گوسین را با این مقادیر محاسبه کنیم، منحنی یکپارچه قرمز رنگ در شکل 10 بدست میآید. این توزیع گوسین در مقادیر صحیح \( x \) به جز مقادیر انتهایی 5,6,29,30 یک منحنی تطبیق شده بر نتایج شبیهسازی با دقت مناسب را بوجود میآورد. همچنین، تابع PMF پرتاب تاس، در مقادیر 5 و 30 به نوعی کوتاه و خلاصه شده است ولی منحنی PDF گوسین دارای دنبالههای نامتناهی است. با افزایش تعداد تاسها در این آزمایش، نمودار PMF به منحنی گوسین نزدیکتر میشود.
بنابراین، نتیجه قابل توجهی به این شرح داریم که افزودن چندین دنباله تصادفی با توزیع یکنواخت مستقل از هم منجر به دنباله تقریبی گوسین میشود. این یک مثال از قضیه حد مرکزی است که به زبان ساده میگوید، مجموع دنبالههای تصادفی مستقل با توزیع احتمال دلخواه، به طور تقریبی گوسین است. به طور معادل، اگر شما یک دنباله را به صورت تصادفی نمونهبرداری کرده تا M دنباله جدید حاصل شود، آنگاه مجموع آن دنبالهها تقریبا گوسین است. همین نکته دلیل اینکه توزیع گوسین در همه جا حضور دارد را توجیه میکند.
شکل 10- تابع PMF پرتاب 5 تاس برای N=100E3. منحنی قرمز رنگ PDF گوسین است.
بخش دوم: شبیهسازی در زبان برنامهنویسی R
شبیهسازی متغیرهای تصادفی با توزیع یکنواخت
در ابتدا اعداد تصادفی از یک توزیع یکنواخت، تولید میکنیم. در یک توزیع یکنواخت، هر مقدار بین دو نقطه (مثلا 0 و 1) دارای احتمال رخداد یکسان با سایر نقاط است.
# Set seed for reproducibility
set.seed(123)
# Number of random variables and sample size
n <- 1000 # Number of samples
m <- 30 # Sample size
# Generate random variables from a uniform distribution between 0 and 1
random_uniform <- matrix(runif(n * m, min = 0, max = 1), ncol = m)
# Display first 6 rows of the generated data
head(random_uniform)
خروجی کد:
[,1] [,2] [,3] [,4] [,5] [,6] [,7] [,8]
[1,] 0.2875775 0.2736227 0.1596740 0.2058269 0.3044642 0.24862988 0.44026102 0.93034086
[2,] 0.7883051 0.5938669 0.1445159 0.9425390 0.8328188 0.98946318 0.39739215 0.59104489
[3,] 0.4089769 0.1601848 0.1491804 0.3793238 0.5936475 0.71712190 0.37154765 0.07974532
[4,] 0.8830174 0.8534302 0.5144343 0.6262401 0.8071966 0.65172829 0.52880857 0.84501857
[5,] 0.9404673 0.8477392 0.4928273 0.1835024 0.2940508 0.24055621 0.07378541 0.02978437
[6,] 0.0455565 0.4778868 0.6163428 0.6592076 0.1410852 0.08679275 0.71684977 0.81465972…………………………….
در این کد، ماتریس با ابعاد \( n \times m \) از اعداد با توزیع یکنواخت تولید شده است که \( n \) تعداد نمونهها (1000) و \( m \) اندازه هر نمونه (30) است. تابع runif اعداد تصادفی با توزیع یکنواخت بین 0 و 1 تولید میکند.
محاسبه میانگین نمونهها
حال میخواهیم میانگین هر نمونه را (به صورت سطر-محور) در داده تصادفی با توزیع یکنواخت تولید شده، محاسبه کنیم.
# Calculate row means (sample means)
sample_means <- rowMeans(random_uniform)
# Display first 6 sample means
head(sample_means)
خروجی:
[1] 0.4460951 0.4409865 0.4923204 0.5938384 0.4729095 0.4935205
در اینجا از تابع rowMeans برای محاسبه میانگین نمونهها در هر سطر ماتریس اعداد تصادفی استفاده میکنیم. با این کار 1000 میانگین نمونه از تعداد 30 متغیر تصادفی یکنواخت بدست میآید.
بررسی قضیه حد مرکزی با رسم نمودار
بر طبق قضیه حد مرکزی، توزیع میانگین نمونهها باید به سمت توزیع نرمال برود. با رسم هیستوگرام میانگینها و برهم نهادن آن بر منحنی توزیع نرمال، میتوان این موضوع را بررسی کرد.
# Load necessary libraries
library(ggplot2)
# Plot histogram of sample means
ggplot(data.frame(sample_means), aes(x = sample_means)) +
geom_histogram(aes(y = ..density..), bins = 30, color = “black”, fill = “lightblue”, alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(sample_means), sd = sd(sample_means)),
color = “red”, size = 1) +
labs(title = “Central Limit Theorem Visualization”,
x = “Sample Means”, y = “Density”) +
theme_minimal()
خروجی:

شکل 11- میانگینهای نمونهها
تابع geom_histogram هیستوگرام میانگینها را تولید میکند که در آن aes(y=..density..) هیستوگرام را به نمودار چگالی احتمال، نرمالیزه میکند.
تابع stat_function منحنی قرمز رنگ توزیع نرمال رو با استفاده از پارامترهای میانگین و واریانس نمونه، روی هیستوگرام میگذارد.
هیستوگرام برای تایید قضیه حد مرکزی باید شبیه یک زنگوله باشد.
تنظیم اندازه نمونهها برای قضیه حد مرکزی
بیایید اثر اندازه نمونه بر نتایج بدست آمده در بالا را برای مقادیر مختلف این اندازه، بررسی کنیم.
# Function to visualize CLT for different sample sizes
visualize_clt <- function(n, m) {
# Generate random uniform variables
random_uniform <- matrix(runif(n * m, min = 0, max = 1), ncol = m)
# Calculate sample means
sample_means <- rowMeans(random_uniform)
# Plot histogram with normal distribution
ggplot(data.frame(sample_means), aes(x = sample_means)) +
geom_histogram(aes(y = ..density..), bins = 30, color = “black”, fill = “lightgreen”, alpha = 0.7) +
stat_function(fun = dnorm, args = list(mean = mean(sample_means), sd = sd(sample_means)),
color = “red”, size = 1) +
labs(title = paste(“CLT with Sample Size”, m),
x = “Sample Means”, y = “Density”) +
theme_minimal()
}
# Visualize CLT with different sample sizes
visualize_clt(1000, 5) # Small sample size
visualize_clt(1000, 50) # Larger sample size
خروجی:

شکل 12- میانگینهای نمونهها
تابع تحت عنوان visualize_clt برای شبیهسازی قضیه حد مرکزی با اندازه نمونههای مختلف (\( m \)) ایجاد شده است.
برای اندازههای کوچک (مثلا 5)، توزیع میانگینها ممکن است خیلی شبیه توزیع نرمال نباشد.
با افزایش اندازه نمونه (مثلا 50)، توزیع میانگینها به یک توزیع نرمال نزدیکتر میشود (که از قضیه حد مرکزی نیز چنین نتیجه میشود)
مقایسه توزیعها
برای مقایسه توزیعهای میانگینها برای اندازه نمونههای مختلف، میتوانیم هیستوگرامها را کنار هم رسم کنیم. با این کار میتوان ملاحظه کرد که قضیه حد مرکزی چگونه با اندازه نمونه بزرگتر، بهتر دیده میشود.
# Combine plots for comparison
library(gridExtra)
p1 <- visualize_clt(1000, 5)
p2 <- visualize_clt(1000, 50)
# Arrange plots side by side
grid.arrange(p1, p2, ncol = 2)
خروجی:

شکل 13- مقایسه توزیع میانگینهای نمونهها با اندازه متفاوت
تابع grid.arrange از بسته gridExtra برای نمایش دو نمودار کنار هم استفاده شده است. نمودار با اندازه نمونه بزرگتر (سمت راست)، دارای توزیع میانگین نمونه با شباهت بیشتر به یک توزیع نرمال است و به وضوح اثر قضیه حد مرکزی را نشان میدهد.
نتیجهگیری
قضیه حد مرکزی، یک مفهوم قدرتمند و اساسی است که به متخصصین آمار امکان استنتاج در مورد پارامترهای یک جمعیت آماری را با استفاده از دادههای نمونه، میدهد. در این مقاله با استفاده از شبیهسازی در محیطهای نرمافزاری متلب و R، نشان دادیم که قضیه حد مرکزی برای نمونههای تصادفی تولید شده از توزیع یکنواخت چگونه قابل تحقیق و بررسی است. با افزایش تعداد نمونهها، همانطور که قضیه حد مرکزی میگوید، هر چه بیشتر توزیع میانگینهای حاصل به یک توزیع نرمال نزدیکتر میشود.
منبع: www.geeksforgeeks.org, www.dsprelated.com