PageSourceSearch

https://www.standarddeviationcalculator.io/web_assets/frontend/script/calculateStaDev.js?v=3.2.839

js standarddeviationcalculator.io collected 2026-10-01 10:38:30 UTC 18,540 bytes, 516 lines download raw bytes

1// This function handles the Standard Deviation calculation workflow
2function StandardDeviation() {
3    // Sanitize and validate input
4    $("#input").val(regexForCommaSepNumbers("#input"));
5    let input = $("#input").val();
6    if (Array.from(input.split(","), Number).includes(NaN)) return validtionExp();
7
8    // Fix trailing comma by adding last number
9    if (input.match(/\,$/g)) {
10        const lastComma = input.lastIndexOf(",");
11        const lastVal = input.slice(lastComma + 1).split(",").map(Number).reduce((a, b) => a + b, 0);
12        $("#input").val(input.slice(0, lastComma) + lastVal);
13        input = $("#input").val();
14    }
15    let numbers = input.split(','); // Splits into ["10", "34", "23", "54", "9"]
16    let count = numbers.length; // Counts the numbers (5)
17
18    // Ensure input is not empty
19    if (input === "") {
20        alert_box("No input found", "Please Enter at least two comma(,) separated values!", BASE_URL + "web_assets/frontend/images/alert_box/no_words.svg");
21        $("#result-tab").hide();
22        return false;
23    }
24
25    // Calculate standard deviation
26    const results = CalculateSD(input);
27    const mean = parseFloat(results.mean);
28
29    // Display results
30    let check_res;
31    if ($("#population1").is(":checked")) {
32        // Population stats
33        $("#sd_sample, #variance_sample").hide();
34        $("#title").text($("#std_population_head").val());
35        check_res = SDSteps(1, mean, results.SD_population);
36    } else {
37        // Sample stats
38        $("#sd_pop, #variance_pop").hide();
39        $("#title").text($("#std_sample_head").val());
40        check_res = SDSteps(0, mean, results.SD_sample);
41    }
42
43    if (check_res == false) {
44        return false;
45    }
46
47    // Common results in sample & population
48    // Use formatValue (not round_off) so the main result matches the step-by-step
49    // solution for very small/large magnitudes — round_off collapses e.g.
50    // 8.1650E-5 to 0.0001, while the steps show the precise scientific value.
51    $("#num").text(count);
52    // SD headline shows 6 decimals (backend ans1 in the steps matches this)
53    $("#sd_pop").text(formatValue(results.SD_population, 6));
54    $("#sd_sample").text(formatValue(results.SD_sample, 6));
55    $("#variance_pop").text(formatValue(results.variance_population));
56    $("#variance_sample").text(formatValue(results.variance_sample));
57
58    $("#result_table").hide();
59    // ", " (not the array's bare-comma join) so narrow screens wrap the list
60    // between numbers instead of splitting one number across two lines
61    $("#diff").text(results.diff.join(", "));
62    $("#diff_sqr").text(results.diff_sqr.join(", "));
63    $("#sum_diff_sqr").text(formatValue(results.sum_diff_sqr));
64    $("#mean_c").text(formatValue(mean));
65    $("#tool_works").hide();
66
67    // Toggle view based on sample or population
68    const isPop = $("#population1").is(":checked");
69    $("#variance_popul, #deviatio_popul, #squared_popula, #sum_of_popula ,#mean_c_population").toggle(isPop);
70    $("#variance_samp, #deviatio_sampl, #squared_sampl, #sum_of_sampl ,#mean_c_sample").toggle(!isPop);
71    $(".calc_btn").attr("disabled", false);
72    setTimeout(() => {
73        $("html, body").animate({ scrollTop: $("#result-tab").offset().top - 100 }, 400);
74    }, 400);
75    $("#tool_results, .res_tab, #result-tab").show();
76}
77
78
79// SDSteps handles the display of solution steps
80function SDSteps(type, mean, stdDev) {
81    $(".calc_btn").attr("disabled", true);
82    let inputValues = $("#input").val().replaceAll(" ", "").split(",").filter(v => !isNaN(parseFloat(v))).map(Number);
83
84    if (inputValues.length < 2) {
85        alert_box("Validation Error", "Minimum required 2 values comma separated <strong>e.g: <code>130,45,475</code></strong>", BASE_URL + "web_assets/frontend/images/alert_box/no_words.svg");
86        $("#result-tab").hide();
87        return false;
88    }
89
90    $.ajaxSetup({ headers: { "X-CSRF-TOKEN": $('meta[name="_token"]').attr("content") } });
91
92    const endpoint = type === 0 ? "/tool/sd_sample" : "/tool/sd_population";
93    const generateFunc = type === 0 ? generate_table : generate_table_population;
94
95    $.ajax({
96        type: "POST",
97        url: endpoint,
98        timeout: 10000,
99        data: {
100            variance: inputValues,
101            mean: mean,
102            SD_sample: stdDev,
103            'e_track_key': getETrackKey()
104        },
105        success: function (response) {
106            const htmlData = response[0];
107            const { multiplystr, veriance, powstr } = response[1];
108
109            const solutionFirst = htmlData.html_first.replace(/\\text{Solution:}/g, $("#php_solution").val())
110                .replace(/\\overline{X}/g, "X̄")
111                .replace(/\\text{Mean = }/g, $("#phpmean").val())
112                .replace(/\\bold{Formula:}/g, $("#phpformula").val());
113            const solutionSecond = htmlData.html_second.replace(/\\textbf{Putting calculated values in the formula:}/g, $("#php_calculated_values").val())
114                .replaceAll(" ", " \\space ");
115
116            render_katex(solutionFirst, "html_first");
117            render_katex(solutionSecond, "html_second");
118
119            const resultTable = generateFunc(multiplystr, veriance, powstr);
120            $("#steps").show();
121            $("#html_table").html($("#php_calculated_values_from_table").val()).append(resultTable);
122            $("#show_step").text("Show Steps");
123
124            setTimeout(() => {
125                $("html, body").animate({ scrollTop: $("#result-tab").offset().top - 100 }, 400);
126            }, 400);
127
128            hideOverlay();
129            renderSDGraph(mean, stdDev);
130            $(".calc_btn").attr("disabled", false);
131        },
132        error: function (XMLHttpRequest, textStatus, errorThrown) {
133            const { message, exception, file, line } = JSON.parse(XMLHttpRequest.responseText || '{}');
134            const fileShort = (file || '').split('\\').pop();
135            save_error(
136                `${message} | ${exception} | ${fileShort}`,
137                "standard-deviation-calculator.js",
138                line || 0,
139                0
140            );
141            $(".calc_btn").attr("disabled", false);
142        }
143    });
144}
145
146let sdChartInstance = null;
147let chartjsLoading = false;
148
149function loadChartJs(callback) {
150    if (typeof Chart !== "undefined") {
151        callback();
152        return;
153    }
154    if (chartjsLoading) {
155        const checkInterval = setInterval(() => {
156            if (typeof Chart !== "undefined") {
157                clearInterval(checkInterval);
158                callback();
159            }
160        }, 100);
161        return;
162    }
163    chartjsLoading = true;
164    const script = document.createElement("script");
165    script.src = "https://cdn.jsdelivr.net/npm/chart.js";
166    script.async = true;
167    script.onload = () => {
168        chartjsLoading = false;
169        callback();
170    };
171    document.head.appendChild(script);
172}
173
174function renderSDGraph(mean, stdDev) {
175    loadChartJs(() => {
176        _executeRenderSDGraph(mean, stdDev);
177    });
178}
179
180function _executeRenderSDGraph(mean, stdDev) {
181    const graphContainer = $("#sdChart").parent();
182    
183    // Check for zero standard deviation to prevent division by zero
184    if (stdDev <= 0) {
185        $("#graph_show").show();
186        // If already initialized as chart, destroy it
187        if (sdChartInstance) sdChartInstance.destroy();
188        // Show a message or a simple line
189        graphContainer.html('<div style="height: 100%; display: flex; align-items: center; justify-content: center; font-family: sans-serif; color: #666; background: #f9f9f9; border-radius: 8px;">Standard Deviation is 0 (All values are identical). No distribution to display.</div>');
190        // We need to restore the canvas for next calculation
191        setTimeout(() => {
192            if ($("#sdChart").length === 0) {
193                graphContainer.html('<canvas id="sdChart"></canvas>');
194            }
195        }, 10);
196        return;
197    }
198
199    // Ensure canvas exists (in case it was replaced by zero-SD message)
200    if ($("#sdChart").length === 0) {
201        graphContainer.html('<canvas id="sdChart"></canvas>');
202    }
203
204    const ctx = document.getElementById('sdChart').getContext('2d');
205    const label = $("#population1").is(":checked") ? 'σ' : 's';
206    const meanLabel = $("#population1").is(":checked") ? 'μ' : 'x̄';
207
208    // Generate data points
209    const points = [];
210    const minX = mean - 4 * stdDev;
211    const maxX = mean + 4 * stdDev;
212    const count = 200;
213    const step = (maxX - minX) / count;
214
215    for (let i = 0; i <= count; i++) {
216        const x = minX + (i * step);
217        const y = (1 / (stdDev * Math.sqrt(2 * Math.PI))) * Math.exp(-0.5 * Math.pow((x - mean) / stdDev, 2));
218        points.push({ x: x, y: y });
219    }
220
221    const peakY = (1 / (stdDev * Math.sqrt(2 * Math.PI)));
222
223    const datasets = [
224        {
225            label: '99.7%',
226            data: points.filter(p => p.x >= mean - 3 * stdDev && p.x <= mean + 3 * stdDev),
227            backgroundColor: 'rgba(100, 100, 255, 0.15)',
228            fill: 'origin',
229            pointRadius: 0,
230            tension: 0.4,
231            borderWidth: 0
232        },
233        {
234            label: '95%',
235            data: points.filter(p => p.x >= mean - 2 * stdDev && p.x <= mean + 2 * stdDev),
236            backgroundColor: 'rgba(100, 100, 255, 0.3)',
237            fill: 'origin',
238            pointRadius: 0,
239            tension: 0.4,
240            borderWidth: 0
241        },
242        {
243            label: '68%',
244            data: points.filter(p => p.x >= mean - stdDev && p.x <= mean + stdDev),
245            backgroundColor: 'rgba(100, 100, 255, 0.45)',
246            fill: 'origin',
247            pointRadius: 0,
248            tension: 0.4,
249            borderWidth: 0
250        },
251        {
252            label: `${label}=${formatValue(stdDev, 6)}`,
253            data: points,
254            borderColor: '#0090d0',
255            borderWidth: 3,
256            pointRadius: 0,
257            fill: false,
258            tension: 0.4
259        },
260        {
261            label: `${meanLabel}=${formatValue(mean)}`,
262            data: [{ x: mean, y: 0 }, { x: mean, y: peakY * 1.05 }],
263            borderColor: '#333',
264            borderWidth: 2,
265            borderDash: [5, 5],
266            pointRadius: 0,
267            fill: false,
268            showLine: true
269        }
270    ];
271
272    if (sdChartInstance) {
273        sdChartInstance.destroy();
274    }
275
276    $("#graph_show").show();
277
278    // Custom plugin to draw percentage labels directly on the graph
279    const percentageLabelsPlugin = {
280        id: 'percentageLabels',
281        afterDraw: (chart) => {
282            const { ctx, chartArea, scales: { x, y } } = chart;
283            ctx.save();
284            ctx.font = "bold 11px 'Noto Serif', serif";
285            ctx.fillStyle = '#444';
286            ctx.textAlign = 'center';
287
288            const labels = [
289                { text: '68%', val: mean + stdDev * 0.5 },
290                { text: '95%', val: mean + stdDev * 1.5 },
291                { text: '99.7%', val: mean + stdDev * 2.5 }
292            ];
293
294            // On narrow (mobile) canvases 1σ spans fewer pixels than a label's
295            // text, so the three labels mash into one blob. Keep a minimum gap:
296            // push overlapping labels right, then pull back anything shoved past
297            // the plot's right edge. Wide canvases already satisfy the gap, so
298            // desktop positions are unchanged.
299            const gap = 6;
300            const items = labels.map(l => ({
301                text: l.text,
302                px: x.getPixelForValue(l.val),
303                w: ctx.measureText(l.text).width
304            }));
305            for (let i = 1; i < items.length; i++) {
306                const minPx = items[i - 1].px + (items[i - 1].w + items[i].w) / 2 + gap;
307                if (items[i].px < minPx) items[i].px = minPx;
308            }
309            for (let i = items.length - 1; i >= 0; i--) {
310                const maxPx = i === items.length - 1
311                    ? chartArea.right - items[i].w / 2
312                    : items[i + 1].px - (items[i + 1].w + items[i].w) / 2 - gap;
313                if (items[i].px > maxPx) items[i].px = maxPx;
314            }
315
316            const py = y.getPixelForValue(peakY * 0.1); // Position near the bottom
317            items.forEach(l => {
318                ctx.fillText(l.text, l.px, py - 5);
319            });
320            ctx.restore();
321        }
322    };
323
324    sdChartInstance = new Chart(ctx, {
325        type: 'line',
326        data: {
327            datasets: datasets
328        },
329        plugins: [percentageLabelsPlugin],
330        options: {
331            responsive: true,
332            maintainAspectRatio: false,
333            interaction: {
334                intersect: false,
335                mode: 'index',
336            },
337            plugins: {
338                title: {
339                    display: true,
340                    text: 'Standard Deviation Graph',
341                    font: { size: 18, weight: 'bold', family: "'Noto Serif', serif" },
342                    color: '#333',
343                    padding: { bottom: 20 }
344                },
345                legend: {
346                    position: 'top',
347                    labels: {
348                        usePointStyle: true,
349                        font: { family: "'Noto Serif', serif" },
350                        filter: function(item, chart) {
351                            return item.text.includes('=');
352                        }
353                    }
354                },
355                tooltip: {
356                    bodyFont: { family: "'Noto Serif', serif" },
357                    titleFont: { family: "'Noto Serif', serif" },
358                    callbacks: {
359                        label: function(context) {
360                            return `x: ${formatValue(context.parsed.x)}, y: ${formatValue(context.parsed.y)}`;
361                        }
362                    }
363                }
364            },
365            scales: {
366                x: {
367                    type: 'linear',
368                    position: 'bottom',
369                    grid: { display: false },
370                    title: { display: false },
371                    ticks: { font: { family: "'Noto Serif', serif" } }
372                },
373                y: {
374                    beginAtZero: true,
375                    grid: { color: '#f5f5f5' },
376                    title: { display: false },
377                    ticks: { font: { family: "'Noto Serif', serif" } }
378                }
379            }
380        }
381    });
382}
383
384// Helper Functions
385
386function showOverlay() {
387    $(".loading-overlay").show();
388    $("span#submit-spinner").hide();
389    $(".preloader").prop("disabled", true);
390}
391
392function hideOverlay() {
393    $(".loading-overlay").hide();
394    $("span#submit-spinner").show();
395    $(".preloader").removeAttr("disabled");
396}
397
398function generate_table(values, diffs, squares) {
399    let rows = "", sumSquares = 0;
400
401    for (let i = 0; i < diffs.length; i++) {
402        const vRaw = (typeof values[i] === 'string') ? Number(values[i]) : values[i];
403        const dRaw = (typeof diffs[i] === 'string') ? Number(diffs[i]) : diffs[i];
404        const sRaw = (typeof squares[i] === 'string') ? Number(squares[i]) : squares[i];
405
406        rows += `<tr>
407            <td>${formatValue(dRaw)}</td>
408            <td>${formatValue(vRaw)}</td>
409            <td>${formatValue(sRaw)}</td>
410        </tr>`;
411
412        sumSquares += Number(sRaw);
413    }
414    return `<div class="cod-table-container">
415        <table class="cod-table">
416            <thead>
417                <tr>
418                    <th>X<sub>i</sub></th>
419                    <th>X<sub>i</sub> - X̄</th>
420                    <th>(X<sub>i</sub> - X̄)<sup>2</sup></th>
421                </tr>
422            </thead>
423            <tbody>
424                ${rows}
425                <tr class="total-row">
426                    <td>--</td>
427                    <td>--</td>
428                    <td>∑(X<sub>i</sub> - X̄)<sup>2</sup> = ${formatValue(sumSquares)}</td>
429                </tr>
430            </tbody>
431        </table>
432    </div>`;
433}
434
435
436function generate_table_population(values, diffs, squares) {
437    let rows = "", sumSquares = 0;
438
439    for (let i = 0; i < diffs.length; i++) {
440        const vRaw = (typeof values[i] === 'string') ? Number(values[i]) : values[i];
441        const dRaw = (typeof diffs[i] === 'string') ? Number(diffs[i]) : diffs[i];
442        const sRaw = (typeof squares[i] === 'string') ? Number(squares[i]) : squares[i];
443
444        rows += `<tr>
445            <td>${formatValue(dRaw)}</td>
446            <td>${formatValue(vRaw)}</td>
447            <td>${formatValue(sRaw)}</td>
448        </tr>`;
449
450        sumSquares += Number(sRaw);
451    }
452
453    return `<div class="cod-table-container">
454        <table class="cod-table">
455            <thead>
456                <tr>
457                    <th>X<sub>i</sub></th>
458                    <th>X<sub>i</sub> - µ</th>
459                    <th>(X<sub>i</sub> - µ)<sup>2</sup></th>
460                </tr>
461            </thead>
462            <tbody>
463                ${rows}
464                <tr class="total-row">
465                    <td>--</td>
466                    <td>--</td>
467                    <td>∑(X<sub>i</sub> - µ)<sup>2</sup> = ${formatValue(sumSquares)}</td>
468                </tr>
469            </tbody>
470        </table>
471    </div>`;
472}
473
474
475function render_katex(expr, elementId = "") {
476    const element = document.getElementById(elementId || "render_katex");
477    try {
478        katex.render(expr, element);
479    } catch (e) {
480        element.innerHTML = `<span class='errorMessage'>${e.message}</span>`;
481    }
482}
483
484$(document).ready(function () {
485    // Handle Enter key on input
486    $(".freq").keydown(function (e) {
487        if (e.which === 13 && !e.shiftKey) {
488            e.preventDefault();
489            $("#input").val(regexForCommaSepNumbers("#input"));
490            calculateStaDev();
491        }
492    });
493
494    // Handle calculate button
495    $(".calc_btn").click(function () {
496        $("#input").val(regexForCommaSepNumbers("#input"));
497        if ($("#population1").is(":checked")) {
498            $("#stan_dev").text("Population");
499            $("#Main_heading_pdf").text("Standard Deviation (p)");
500            population("SD");
501        } else {
502            $("#stan_dev").text("Sample");
503            $("#Main_heading_pdf").text("Standard Deviation (s)");
504            sample("SD");
505        }
506    });
507
508    // Reset button
509    $(".res_btn").click(function () {
510        $("#result_table").hide();
511        $("#tool_results").hide();
512        $("#tool_works").show();
513        $("#result-tab").hide();
514        $("#input").val("");
515    });
516});

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.