TL;DR: мне нужен способ создать полином из некоторых заданных координат таким образом, чтобы можно было перебирать его коэффициенты и, возможно, даже позволять оценивать полином в любой заданной точке.
Я работаю над созданием грубого алгоритма на JavaScript/TypeScript для обязательств KZG, и один из шагов этого алгоритма включает в себя умножение коэффициентов полинома, построенного для некоторой заданной строки, на структурированную ссылочную строку (SRS), возведенную в соответствующую степень.
В любом случае, по сути, это означает, что мне нужно перебрать все коэффициенты этого вновь построенного многочлена (по крайней мере, я думаю, что мне нужно это сделать, я открыт для предложений здесь).
Я пытаюсь добиться следующего:
Я застрял на шаге 4).
Я знаю, как построить многочлен из заданной строки в JS/TS с использованием интерполяции Лагранжа, но у меня возникают трудности с извлечением его коэффициентов, которые мне нужны, чтобы иметь возможность умножать их с помощью SRS.
Ниже приведен мой алгоритм интерполяции Лагранжа — обратите внимание, что он может решить 5) для меня, но я не вижу очевидного способа получить из него точные коэффициенты:
type Point = { x: number; y: number };
// The function basically reconstructs the whole Lagrange Polynomial each time
// it needs to evaluate it at some given point `newX`, which is a problem as
// there is no way to extract the coefficients.
function lagrangeInterpolation(points: Point[], newX: number) {
const n = points.length;
let newY = 0;
for (let i = 0; i < n; i++) {
let { x, y } = points[i];
let term = y;
for (let j = 0; j < n; j++) {
if (i !== j) {
let { x: xj } = points[j];
term = (term * (newX - xj)) / (x - xj);
}
}
newY = newY + term;
}
return newY;
}
Может быть, другой алгоритм интерполяции позволил бы вычислить точные коэффициенты?
Я не смог найти ни одной библиотеки JS, которая бы решала именно эту проблему. Ближайшими из них мне удалось найти следующие, но они пока неприменимы для решения этой задачи:
Посмотрите это и эту ссылку.



![Безумие обратных вызовов в javascript [JS]](https://i.imgur.com/WsjO6zJb.png)


Вы можете использовать матричный метод, описанный @guest в Коэффициенты полиномов Лагранжа.
Для этого вам понадобится функция, вычисляющая определитель матрицы. Для этого вы можете использовать метод исключения Гаусса.
Вот реализация:
function determinant(mat) { // Gaussian elimination method
const n = mat.length;
let det = 1;
for (let r = 0; r < n; r++) {
let r2 = r;
while (!mat[r2][r]) {
r2++;
if (r2 >= mat.length) return 0;
}
const row = mat[r2];
if (r2 !== r) { // Swap rows
mat[r2] = mat[r];
mat[r] = row;
det = -det;
}
let div = row[r];
if (!div) return 0;
det *= div;
for (let c = r; c < n; c++) row[c] /= div;
for (let r2 = r+1; r2 < n; r2++) {
const row2 = mat[r2];
const mul = row2[r];
for (let c = r; c < n; c++) {
row2[c] -= mul * row[c];
}
}
}
return det;
}
// Similar to https://math.stackexchange.com/a/3253643/341715
function lagrangeInterpolationCoefficients(points) {
const lagrangeDet = (j) => determinant(points.map((_, i) =>
points.map(([a, b]) => i == j ? b : a ** i)
));
const denom = lagrangeDet(-1);
return points.map((_, j) => lagrangeDet(j) / denom);
}
const coefficientsToFunction = (coefficients) =>
x => coefficients.reduce((sum, coeff, i) => sum + coeff * x**i, 0);
// Simple (imperfect) rendering of the polynomial:
const coefficientsToString = (coefficients) =>
coefficients.map((coeff, i) => `${coeff}x^${i}`)
.reverse().join(" + ")
.replace(/x\^0|\^1\b|\b0x\^\d+/g, "")
.replaceAll("+ -", "- ");
// Demo
const points = [[0, -1], [1, 1], [3, 8], [4, 10]];
const coefficients = lagrangeInterpolationCoefficients(points);
console.info("f(x) = ", coefficientsToString(coefficients));
const f = coefficientsToFunction(coefficients);
// Verify that the created function returns
// the correct results for the given points
for (const [x, y] of points) {
console.info({x, y, "f(x)": f(x)});
}Это понятный и понятный алгоритм, спасибо. Я только что добавил недостающий \ рядом с последним ^ в предоставленное вами регулярное выражение (\b0x^\d+ должно быть \b0x\^\d+), теперь отлично работает.
Исправленный! Рад, что этот ответ вам пригодится.
На этом шаге вы не застряли: «Вычислите полином, проходящий через эти координаты». Как? Можете ли вы добавить входы и ожидаемые результаты? Я предполагаю, что вы хотите протестировать все возможные полиномы?