Добавил:
Опубликованный материал нарушает ваши авторские права? Сообщите нам.
Вуз: Предмет: Файл:

interpolation

.js
Скачиваний:
9
Добавлен:
31.03.2021
Размер:
4.17 Кб
Скачать
// Заданная функция
function f(x) {
    return Math.sin(x)
}

// Вторая производная заданной функции
function fDerivative2(x) {
    return -Math.sin(x);
}

/**
 * Кубический сплайн
 * @param {number} x - текущий аргумент
 * @param {number} i - номер точки
 * @param {number[]} M - массив вторых производных кубического сплайна, M[i] = S3''[i]
 * @param {number[]} X - массив аргументов
 */
function S3(x, i, h, M, X) {
    return M[i-1] * ((X[i]-x)**3 - h**2 * (X[i] - x)) / (6*h)
        + M[i] * ((x - X[i-1])**3 - h**2 * (x - X[i-1])) / (6*h)
        + f(X[i-1]) * (X[i] - x) / h
        + f(X[i]) * (x - X[i-1]) / h
}

/**
 * Метод прогонки
 * краевые условия S3''(a)=f''(a), S3''(b)=f''(b)
 * @param {Function} f - заданная функция
 * @param {Function} der2 - 2 производная заданной функции
 * @param {number} f0 - начало отрезка
 * @param {number} fn - конец отрезка
 * @param {number} h - длина шага
 * @param {number} n - кол-во частичных отрезков
 * @param {number[]} X - массив аргументов
 * @returns {number[]} M - массив вторых производных кубического сплайна
 */
function TMA(f, der2, f0, fn, h, n, X) {
    // согласно краевым условиям 
    ai = 2 * h / 3
    bi = h / 6
    ci = h / 6

    a0 = 1
    b0 = 0

    an = 1
    cn = 0

    // правая часть СЛУ
    const d = []
    d[0] = der2(f0) // f''(0) = -sin(0)
    d[n] = der2(fn) // f''(Pi) = -sin(Pi)

    // Yi = (Yi+1 - Yi)/h - (Yi - Yi-1)/h
    for (let i = 1; i < n; i++) {
        d[i] = (f(X[i+1]) - f(X[i]))/h - (f(X[i]) - f(X[i-1]))/h
    }

    // Прогоночные коэффициенты
    const l = []
    const u = []

    l[0] = -b0 / a0 // 0
    u[0] = d[0] / a0 // 0

    // заполняем согласно рекуррентным формулам
    for (let i = 1; i < n; i++) {
        l[i] = -bi / (ai + ci * l[i-1])
        u[i] = (d[i] - ci * u[i-1]) / (ai + ci * l[i-1])
    }

    // и крайнюю точку
    l[n] = -bi / (an + cn * l[n-1])
    u[n] = (d[n] - cn * u[n-1]) / (an + cn * l[n-1])

    
    const M = []
    M[n] = u[n] // т.к. bn=0

    // Mi = li * Mi+1 + ui
    for (let i = n-1; i >= 0; i--) {
        M[i] = l[i] * M[i+1] + u[i]   
    }

    return M;
}

function main() {
    const a = 0
    const b = Math.PI

    const result = []

    let prevMax = 0
    let h
    for (let n = 5; n <= 5120; n *= 2) {
        // длина шага
        h = (b - a) / n

        // разбиваем на частичные отрезки
        const X = [a]
        for (let i = 1; i < n; i++) {
            X.push(a + i*h)   
        }
        X.push(b)

        // получаем вторые производные кубического сплайна методом прогонки
        const M = TMA(f, fDerivative2, a, b, h, n, X)

        let deltaMax = 0
        let ocenka = 0
        for (let i = 1; i < n+1; i++) {
            // |S3(x) - f(x)| в серединах частичных отрезков
            const s3 = S3(X[i-1] + h/2, i, h, M, X)
            ocenka = Math.abs(s3 - f(X[i-1] + h/2))

            deltaMax = Math.max(deltaMax, ocenka)  
        }

        result.push({
            // кол-во частичных отрезков
            n,

            // максимальная погрешность
            deltaMax, 

            // оценка погрешности (четвертый порядок точности)
            deltaOc: prevMax / (2**4), 

            // отношение погрешности пред. строки к текущей
            K: prevMax / deltaMax, 
        })
        prevMax = deltaMax
    }

    console.table(result)
}

main()
Соседние файлы в предмете Методы вычислений