112 lines
2.3 KiB
JavaScript
112 lines
2.3 KiB
JavaScript
|
|
/*
|
||
|
|
* Copyright (C) 2026 filifa
|
||
|
|
*
|
||
|
|
* License: 0BSD (https://spdx.org/licenses/0BSD.html)
|
||
|
|
*/
|
||
|
|
let exp = null;
|
||
|
|
let s = null;
|
||
|
|
|
||
|
|
function stirling2(p) {
|
||
|
|
if (p === 0) {
|
||
|
|
return [1n];
|
||
|
|
}
|
||
|
|
|
||
|
|
let s = [0n];
|
||
|
|
for (let i = 1; i < p + 1; i++) {
|
||
|
|
s.push(1n);
|
||
|
|
for (let j = i - 1; j > 0; j--) {
|
||
|
|
s[j] = BigInt(j) * s[j] + s[j-1];
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
return s;
|
||
|
|
}
|
||
|
|
|
||
|
|
function faulhaber(n, s) {
|
||
|
|
const limit = BigInt(s.length);
|
||
|
|
if (limit === 1n) {
|
||
|
|
return n;
|
||
|
|
}
|
||
|
|
|
||
|
|
let q = n + 1n;
|
||
|
|
let total = 0n;
|
||
|
|
for (let k = 1n; k < limit; k++) {
|
||
|
|
q *= n + 1n - k;
|
||
|
|
total += s[k] * q / (k + 1n);
|
||
|
|
}
|
||
|
|
|
||
|
|
return total;
|
||
|
|
}
|
||
|
|
|
||
|
|
function calculate() {
|
||
|
|
const limit = document.querySelector("#limit");
|
||
|
|
const exponent = document.querySelector("#exponent");
|
||
|
|
|
||
|
|
const e = parseInt(exponent.value)
|
||
|
|
if (exp === null || exp !== e) {
|
||
|
|
exp = e;
|
||
|
|
s = stirling2(exp);
|
||
|
|
}
|
||
|
|
|
||
|
|
const n = BigInt(limit.value);
|
||
|
|
const r = faulhaber(n, s);
|
||
|
|
const result = document.querySelector("#result");
|
||
|
|
result.value = r;
|
||
|
|
}
|
||
|
|
|
||
|
|
function calculateStirling() {
|
||
|
|
const limit = document.querySelector("#stirling-limit");
|
||
|
|
const p = parseInt(limit.value)
|
||
|
|
s = stirling2(p);
|
||
|
|
|
||
|
|
const table = buildTable(s);
|
||
|
|
const result = document.querySelector("#stirling-result");
|
||
|
|
while (result.firstChild) {
|
||
|
|
result.removeChild(result.firstChild);
|
||
|
|
}
|
||
|
|
result.appendChild(table);
|
||
|
|
}
|
||
|
|
|
||
|
|
function buildTable(values) {
|
||
|
|
const table = document.createElement("table");
|
||
|
|
const caption = document.createElement("caption");
|
||
|
|
caption.textContent = "Stirling numbers S(p,k) from k=0 to k=p";
|
||
|
|
table.appendChild(caption);
|
||
|
|
|
||
|
|
const tbody = document.createElement("tbody");
|
||
|
|
table.appendChild(tbody);
|
||
|
|
|
||
|
|
const n = values.length;
|
||
|
|
const ks = Array(n);
|
||
|
|
for (let i = 0; i < n; i++) {
|
||
|
|
ks[i] = i;
|
||
|
|
}
|
||
|
|
|
||
|
|
const nrow = buildRow("k", ks);
|
||
|
|
tbody.appendChild(nrow);
|
||
|
|
|
||
|
|
const vrow = buildRow("S(p,k)", values);
|
||
|
|
tbody.appendChild(vrow);
|
||
|
|
|
||
|
|
return table;
|
||
|
|
}
|
||
|
|
|
||
|
|
function buildRow(htext, values) {
|
||
|
|
const row = document.createElement("tr");
|
||
|
|
const head = document.createElement("th");
|
||
|
|
head.textContent = htext;
|
||
|
|
row.appendChild(head);
|
||
|
|
|
||
|
|
const n = values.length;
|
||
|
|
for (let i = 0; i < n; i++) {
|
||
|
|
const elem = document.createElement("td");
|
||
|
|
elem.textContent = values[i];
|
||
|
|
row.appendChild(elem);
|
||
|
|
}
|
||
|
|
|
||
|
|
return row;
|
||
|
|
}
|
||
|
|
|
||
|
|
document.querySelector("#enter").addEventListener("click", () => calculate())
|
||
|
|
document.querySelector("#stirling-enter").addEventListener("click", () => calculateStirling())
|