Перейти к основному содержимому
clawam tools
Инструменты Документы Daoark EN Главная Главная / Calculadora › Главная manifest.json 0; }); var pts = []; for (var i = 0; i < lines.length; i++) { var parts = lines[i].split(/[\s,;\t]+/).filter(function(x) { return x.length > 0; }); if (parts.length >= 2) { var x = parseFloat(parts[0]); var y = parseFloat(parts[1]); if (!isNaN(x) && !isNaN(y)) pts.push([x, y]); } } return pts; } function linreg(pts) { var n = pts.length; var sumX = 0, sumY = 0, sumXY = 0, sumXX = 0, sumYY = 0; for (var i = 0; i < n; i++) { sumX += pts[i][0]; sumY += pts[i][1]; sumXY += pts[i][0] * pts[i][1]; sumXX += pts[i][0] * pts[i][0]; sumYY += pts[i][1] * pts[i][1]; } var meanX = sumX / n, meanY = sumY / n; var num = sumXY - n * meanX * meanY; var denX = sumXX - n * meanX * meanX; var denY = sumYY - n * meanY * meanY; if (denX === 0) throw new Error('x 全相同'); var b = num / denX; var a = meanY - b * meanX; var ssTot = denY; var ssRes = 0; for (var j = 0; j < n; j++) { var pred = a + b * pts[j][0]; ssRes += (pts[j][1] - pred) * (pts[j][1] - pred); } var r2 = ssTot > 0 ? 1 - ssRes / ssTot : 0; var r = (ssTot > 0 && denX > 0) ? num / Math.sqrt(denX * denY) : 0; var stdErr = n > 2 ? Math.sqrt(ssRes / (n - 2)) : NaN; return { a: a, b: b, r2: r2, r: r, n: n, meanX: meanX, stdErr: stdErr, ssRes: ssRes }; } // t 分布 95% 临界值表(简化,df=1..30) function tCrit95(df) { var t = { 1: 12.706, 2: 4.303, 3: 3.182, 4: 2.776, 5: 2.571, 6: 2.447, 7: 2.365, 8: 2.306, 9: 2.262, 10: 2.228, 15: 2.131, 20: 2.086, 30: 2.042, 60: 2.000, 120: 1.980, 10000: 1.960 }; if (df >= 10000) return 1.96; var keys = Object.keys(t).map(function(k) { return parseInt(k); }).sort(function(a, b) { return a - b; }); if (df >= keys[keys.length - 1]) return t[keys[keys.length - 1]]; for (var i = 0; i < keys.length - 1; i++) if (df >= keys[i] && df < keys[i + 1]) { var t1 = t[keys[i]], t2 = t[keys[i + 1]]; var ratio = (df - keys[i]) / (keys[i + 1] - keys[i]); return t1 + (t2 - t1) * ratio; } return t[keys[0]]; } function doProcess() { try { var pts = parsePairs(getVal('text-a')); if (pts.length < 3) { showError('至少 3 个数据点'); return; } var reg = linreg(pts); var out = '样本量: n = ' + reg.n + '\n' + '回归方程: y = ' + reg.a.toFixed(4) + ' + ' + reg.b.toFixed(4) + 'x\n' + '斜率 b = ' + reg.b.toFixed(6) + ' (x 每增 1,y 平均变 ' + reg.b.toFixed(4) + ')\n' + '截距 a = ' + reg.a.toFixed(6) + '\n' + 'R² = ' + reg.r2.toFixed(6) + ' (' + (reg.r2 * 100).toFixed(2) + '% 的变异由 x 解释)\n' + '相关系数 r = ' + reg.r.toFixed(6) + '\n' + '标准误 SE = ' + (isNaN(reg.stdErr) ? 'N/A' : reg.stdErr.toFixed(6)) + '\n' + '相关强度: ' + (Math.abs(reg.r) > 0.8 ? '强' : Math.abs(reg.r) > 0.5 ? '中' : '弱'); if (!isNaN(reg.stdErr)) { var t95 = tCrit95(reg.n - 2); out += '\n95% 置信区间(均值预测):\n'; // 简单平均预测区间(无新 x 的均值不确定性) out += ' 总体平均 y 的 95% CI: ' + reg.a.toFixed(4) + ' + ' + reg.b.toFixed(4) + 'x ± ' + (t95 * reg.stdErr).toFixed(4); } var predXStr = getVal('predict-x').trim(); if (predXStr) { var xs = predXStr.split(/[\s,;]+/).filter(function(x) { return x.length > 0; }).map(function(x) { return parseFloat(x); }).filter(function(x) { return !isNaN(x); }); if (xs.length > 0) { out += '\n\n预测点(点估计):'; for (var i = 0; i < xs.length; i++) { var y = reg.a + reg.b * xs[i]; out += '\n x=' + xs[i] + ' → ŷ = ' + y.toFixed(4); } } } out += '\n\n前 5 个残差(实际-预测):'; for (var k = 0; k < Math.min(5, reg.n); k++) { var p = reg.a + reg.b * pts[k][0]; out += '\n (' + pts[k][0] + ',' + pts[k][1] + ') 预测 ' + p.toFixed(4) + ' 残差 ' + (pts[k][1] - p).toFixed(4); } showResult(out, 'OLS 线性回归, n=' + reg.n); } catch (e) { showError('计算失败: ' + (e.message || e)); } } $('btn-main').addEventListener('click', function(e) { e.preventDefault(); doProcess(); }); $('btn-clear').addEventListener('click', function() { var inputs = document.querySelectorAll('input,textarea,select'); for (var i = 0; i < inputs.length; i++) { if (inputs[i].tagName === 'SELECT') inputs[i].selectedIndex = 0; else inputs[i].value = inputs[i].defaultValue; } var ra = $('result-area'); ra.hidden = true; ra.style.display = 'none'; var em = $('error-msg'); em.hidden = true; em.style.display = 'none'; }); })();