Allclose: примеры (PYTHON)
allclose(a, b[, rtol, atol, equal_nan]): boolФункция allclose в NumPy
Функция numpy.allclose применяется для проверки приблизительного равенства двух массивов в пределах заданных допусков. Она часто используется в вычислительных задачах, где из-за погрешностей представления чисел с плавающей запятой точное равенство маловероятно, например, в машинном обучении, научных расчетах и обработке сигналов.
Синтаксис функции: numpy.allclose(a, b, rtol=1e-05, atol=1e-08, equal_nan=False).
Аргументы функции:
- a, b (array_like): входные массивы для сравнения.
- rtol (float): относительный допуск. Это максимально допустимая разница между элементами
aиb, выраженная относительно абсолютного значенияb(илиa). По умолчанию установлено значение 1e-05. - atol (float): абсолютный допуск. Это максимально допустимая абсолютная разница между элементами. Значение по умолчанию - 1e-08.
- equal_nan (bool): флаг, определяющий, должны ли значения NaN считаться равными. Если установлено значение True, то NaN в одном массиве будет считаться равным NaN в другом массиве. По умолчанию False.
Функция возвращает True, если все элементы массивов a и b удовлетворяют условию: |a - b| ≤ (atol + rtol * |b|). В противном случае возвращается False.
Примеры использования allclose
Базовое сравнение двух массивов с допусками по умолчанию.
import numpy as np
a = np.array([1.0, 2.0, 3.0])
b = np.array([1.00001, 2.00001, 3.00001])
result = np.allclose(a, b)
print(result)True
Использование пользовательских относительного и абсолютного допусков.
import numpy as np
a = np.array([1.0, 2.0, 3.0])
b = np.array([1.1, 2.1, 3.1])
result = np.allclose(a, b, rtol=0.15, atol=0.0)
print(result)True
Сравнение массивов с разными значениями и проверка влияния абсолютного допуска.
import numpy as np
a = np.array([0.0, 0.0, 0.0])
b = np.array([0.001, 0.001, 0.001])
result = np.allclose(a, b, rtol=1e-05, atol=0.001)
print(result)True
Использование параметра equal_nan для сравнения массивов, содержащих NaN.
import numpy as np
a = np.array([1.0, np.nan, 3.0])
b = np.array([1.0, np.nan, 3.0])
result_without_nan = np.allclose(a, b, equal_nan=False)
result_with_nan = np.allclose(a, b, equal_nan=True)
print(f'equal_nan=False: {result_without_nan}')
print(f'equal_nan=True: {result_with_nan}')equal_nan=False: False equal_nan=True: True
Похожие функции в Python
В Python существует несколько функций для приближенного сравнения, каждая со своей областью применения.
- numpy.isclose: поэлементное сравнение двух массивов, возвращает булев массив, указывающий, какие элементы близки. Полезно для анализа различий в конкретных позициях.
- math.isclose: функция из стандартной библиотеки math для сравнения двух скалярных значений с плавающей запятой. Используется, когда работают с отдельными числами, а не с массивами.
- numpy.array_equal: проверяет точное равенство двух массивов, включая форму и тип данных. Не использует допуски, поэтому подходит для случаев, когда требуется строгое совпадение.
- numpy.all в комбинации с операторами: можно вручную задать условие сравнения, например,
np.all(np.abs(a - b) <= tolerance). Это дает больше гибкости, но требует написания дополнительного кода.
Функцию allclose предпочтительнее использовать для быстрой проверки глобального приблизительного равенства массивов. numpy.isclose применяют, когда нужна информация о различиях по элементам. math.isclose подходит для скалярных операций.
Типичные ошибки при использовании allclose
Ошибки часто связаны с непониманием параметров функции или особенностей типов данных.
Использование функции с массивами разной формы приводит к ValueError.
import numpy as np
a = np.array([1, 2, 3])
b = np.array([1, 2])
try:
result = np.allclose(a, b)
except Exception as e:
print(f'Ошибка: {type(e).__name__}: {e}')Ошибка: ValueError: operands could not be broadcast together with shapes (3,) (2,)
Неправильная интерпретация параметров rtol и atol может привести к неожиданным результатам.
import numpy as np
a = np.array([0.0])
b = np.array([0.1])
result = np.allclose(a, b, rtol=1e-05, atol=0.0)
print(f'С atol=0.0: {result}')
result2 = np.allclose(a, b, rtol=1e-05, atol=0.11)
print(f'С atol=0.11: {result2}')С atol=0.0: False С atol=0.11: True
Сравнение значений целочисленного типа может не требовать допусков, но функция все равно применяет формулу с плавающей запятой.
import numpy as np
a = np.array([1, 2, 3], dtype=int)
b = np.array([1, 2, 4], dtype=int)
result = np.allclose(a, b)
print(result)False
Попытка сравнить массивы, содержащие нечисловые данные, приводит к TypeError.
import numpy as np
a = np.array([1, 2, 'text'])
b = np.array([1, 2, 'text'])
try:
result = np.allclose(a, b)
except Exception as e:
print(f'Ошибка: {type(e).__name__}: {e}')Ошибка: TypeError: ufunc 'subtract' did not contain a loop with signature matching types (dtype(' dtype(' Изменения в последних версиях
В NumPy 1.10.0 был добавлен параметр equal_nan. До этой версии сравнение массивов, содержащих NaN, всегда возвращало False, так как NaN не равен самому себе. С введением параметра появилась возможность учитывать NaN как равные значения.
В более ранних версиях изменения касались в основном улучшения производительности и исправления ошибок в алгоритмах сравнения. Рекомендуется использовать актуальные версии NumPy для получения всех улучшений.
Расширенные примеры применения allclose
Сравнение многомерных массивов. Функция автоматически обрабатывает массивы любой размерности.
import numpy as np
a = np.array([[1.0, 2.0], [3.0, 4.0]])
b = np.array([[1.000009, 2.000009], [3.000009, 4.000009]])
result = np.allclose(a, b)
print(f'Многомерные массивы: {result}')Многомерные массивы: True
Использование allclose для проверки сходимости итерационных алгоритмов, например, в методе Ньютона.
import numpy as np
def newton_method(f, df, x0, tol=1e-6, max_iter=100):
x = x0
for i in range(max_iter):
x_new = x - f(x) / df(x)
if np.allclose(x_new, x, rtol=0, atol=tol):
print(f'Сходимость достигнута на итерации {i+1}')
return x_new
x = x_new
return x
f = lambda x: x**2 - 2
df = lambda x: 2*x
root = newton_method(f, df, 1.0)
print(f'Приближенный корень: {root}')Сходимость достигнута на итерации 6 Приближенный корень: 1.4142135623730951
Применение функции в тестировании научных вычислений, где ожидаются определенные значения с известной погрешностью.
import numpy as np
# Предположим, вычислено значение интеграла
computed_value = 2.999999995
# Ожидаемое значение
expected_value = 3.0
# Проверка с учетом погрешности метода
assert np.allclose(computed_value, expected_value, rtol=1e-8, atol=1e-8), "Тест не пройден"
print("Тест пройден успешно")Тест пройден успешно
Сравнение комплексных чисел. Функция корректно работает с массивами комплексных чисел, сравнивая вещественные и мнимые части отдельно.
import numpy as np
a = np.array([1+2j, 3+4j])
b = np.array([1.00001+2.00001j, 3.00001+4.00001j])
result = np.allclose(a, b)
print(f'Комплексные числа: {result}')Комплексные числа: True
Использование allclose вместе с масками для выборочного сравнения подмассивов.
import numpy as np
a = np.array([1.0, 2.0, np.nan, 4.0])
b = np.array([1.0, 2.0, np.nan, 4.00001])
# Создаем маску, исключающую позиции с NaN
mask = ~(np.isnan(a) | np.isnan(b))
result = np.allclose(a[mask], b[mask])
print(f'Сравнение с маской: {result}')Сравнение с маской: True
Сравнение массивов с разными типами данных, но совместимыми значениями.
import numpy as np
a = np.array([1, 2, 3], dtype=np.float32)
b = np.array([1.00001, 2.00001, 3.00001], dtype=np.float64)
result = np.allclose(a, b)
print(f'Разные типы данных: {result}')Разные типы данных: True
Альтернативы в других языках программирования
В различных языках программирования нет прямой аналогии функции allclose, но реализуют похожую логику сравнения с допуском.
JavaScript: сравнение с использованием абсолютной разности.
function allClose(arr1, arr2, rtol = 1e-05, atol = 1e-08) {
if (arr1.length !== arr2.length) return false;
for (let i = 0; i < arr1.length; i++) {
if (Math.abs(arr1[i] - arr2[i]) > (atol + rtol * Math.abs(arr2[i]))) {
return false;
}
}
return true;
}
console.log(allClose([1.0, 2.0], [1.00001, 2.00001]));true
Java: использование цикла для сравнения элементов массива.
public class AllClose {
public static boolean allClose(double[] a, double[] b, double rtol, double atol) {
if (a.length != b.length) return false;
for (int i = 0; i < a.length; i++) {
if (Math.abs(a[i] - b[i]) > (atol + rtol * Math.abs(b[i]))) {
return false;
}
}
return true;
}
public static void main(String[] args) {
double[] a = {1.0, 2.0};
double[] b = {1.00001, 2.00001};
System.out.println(allClose(a, b, 1e-05, 1e-08));
}
}true
PHP: сравнение массивов с помощью цикла.
function allClose($a, $b, $rtol = 1e-05, $atol = 1e-08) {
if (count($a) !== count($b)) return false;
foreach ($a as $i => $val) {
if (abs($val - $b[$i]) > ($atol + $rtol * abs($b[$i]))) {
return false;
}
}
return true;
}
$a = [1.0, 2.0];
$b = [1.00001, 2.00001];
echo allClose($a, $b) ? 'true' : 'false';true
SQL: прямое сравнение значений с допуском в условиях WHERE.
SELECT * FROM table_name
WHERE ABS(column_a - column_b) <= 1e-08 + 1e-05 * ABS(column_b);C#: использование метода для сравнения массивов.
using System;
class AllClose {
static bool AllCloseFunc(double[] a, double[] b, double rtol = 1e-05, double atol = 1e-08) {
if (a.Length != b.Length) return false;
for (int i = 0; i < a.Length; i++) {
if (Math.Abs(a[i] - b[i]) > (atol + rtol * Math.Abs(b[i]))) {
return false;
}
}
return true;
}
static void Main() {
double[] a = { 1.0, 2.0 };
double[] b = { 1.00001, 2.00001 };
Console.WriteLine(AllCloseFunc(a, b));
}
}True
Lua: итерация по таблицам.
function allClose(a, b, rtol, atol)
rtol = rtol or 1e-05
atol = atol or 1e-08
if #a ~= #b then return false end
for i = 1, #a do
if math.abs(a[i] - b[i]) > (atol + rtol * math.abs(b[i])) then
return false
end
end
return true
end
local a = {1.0, 2.0}
local b = {1.00001, 2.00001}
print(allClose(a, b))true
Golang: сравнение срезов.
package main
import (
"fmt"
"math"
)
func allClose(a, b []float64, rtol, atol float64) bool {
if len(a) != len(b) {
return false
}
for i := range a {
if math.Abs(a[i]-b[i]) > (atol + rtol*math.Abs(b[i])) {
return false
}
}
return true
}
func main() {
a := []float64{1.0, 2.0}
b := []float64{1.00001, 2.00001}
fmt.Println(allClose(a, b, 1e-05, 1e-08))
}true
Kotlin: использование встроенных функций для массивов.
fun allClose(a: DoubleArray, b: DoubleArray, rtol: Double = 1e-05, atol: Double = 1e-08): Boolean {
if (a.size != b.size) return false
return a.indices.all { i ->
Math.abs(a[i] - b[i]) <= (atol + rtol * Math.abs(b[i]))
}
}
fun main() {
val a = doubleArrayOf(1.0, 2.0)
val b = doubleArrayOf(1.00001, 2.00001)
println(allClose(a, b))
}true