Консервативная интервальная арифметическая библиотека в Javascript

Есть ли хорошая библиотека для консервативной интервальной арифметики в Javascript?

Под консервативным я подразумеваю, что с учетом двух интервалов, представляющих диапазоны действительных чисел (конечные точки которых являются плавающей точкой), их сумма интервалов содержит все суммы действительных чисел из исходных интервалов, и аналогично для других операций. Единственная библиотека, найденная при быстром поиске, это https://github.com/Jeff-Tian/JavaScriptIntervalArithmetic, но она не выглядит консервативной.

Поскольку у нас нет доступа к режимам округления, хорошо (на самом деле предпочтительнее для скорости), если интервалы не оптимальны. Например, было бы хорошо, если бы квадрат числа был консервативно аппроксимирован [(1-epsilon)*(x*x),(1+epsilon)*(x*x)]даже если это больше, чем оптимальный интервал с плавающей запятой.

2 ответа

Решение

Взгляните на https://github.com/maurizzzio/interval-arithmetic чьи интервалы представляют числа с плавающей запятой, ограничивая его следующим / предыдущим числом с плавающей запятой двойной точности, которое может быть представлено

var Interval = require('interval-arithmetic');

// { lo: 0.3333333333333333, hi: 0.3333333333333333 }
new Interval().singleton(1 / 3); 

// { lo: 0.33333333333333326, hi: 0.33333333333333337 }
new Interval().boundedSingleton(1 / 3);

Типизированные массивы теперь предоставляют способ работы с байтами, которые составляют плавающее число двойной точности, библиотека изменяет последний бит значения и этого представления здесь, и все операции переносят эту ошибку округления.

Я не совсем уверен, что вы подразумеваете под "консервативным", но я думаю, что добавление к прототипу Array должно быть быстрее, чем создание пользовательских объектов, и вам нужно только реализовать методы, которые вы хотите.

Array.prototype._interval_plus = function (arr2) {
    return [this[0] + arr2[0], this[1] + arr2[1]];
};
Array.prototype._interval_minus = function (arr2) {
    return [this[0] - arr2[0], this[1] - arr2[1]];
};
Array.prototype._interval_multiply = function (arr2) {
    var ac = this[0] * arr2[0],
        ad = this[0] * arr2[1],
        bc = this[1] * arr2[0],
        bd = this[1] * arr2[1];
    return [Math.min(ac, ad, bc, bd), Math.max(ac, ad, bc, bd)];
};
Array.prototype._interval_divide = function (arr2) {
    var ac, ad, bc, bd;
    if (arr2[0] === 0 || arr2[1] === 0)
        throw new Error('division by zero');
    ac = this[0] / arr2[0],
    ad = this[0] / arr2[1],
    bc = this[1] / arr2[0],
    bd = this[1] / arr2[1];
    return [Math.min(ac, ad, bc, bd), Math.max(ac, ad, bc, bd)];
};
Array.prototype._interval_pow = function (arr2, pow) {
    var ac = this[0] * Math.pow(arr2[0], pow),
        ad = this[0] * Math.pow(arr2[1], pow),
        bc = this[1] * Math.pow(arr2[0], pow),
        bd = this[1] * Math.pow(arr2[1], pow);
    return [Math.min(ac, ad, bc, bd), Math.max(ac, ad, bc, bd)];
};

Теперь вы можете делать такие вещи, как

var x = [ 0  ,  1  ];
    y = [ 0.5,  3.5];
x._interval_plus(y)     // [ 0.5 ,   4.5 ]
 ._interval_multiply(y) // [ 0.25,  15.75]
 ._interval_minus(y)    // [-0.25,  12.25]
 ._interval_pow(y, 2);  // [-3.0625, 150.0625]
Другие вопросы по тегам