Машинный ноль

Материал из Энциклопедия о программировании
Перейти к: навигация, поиск

Машинный ноль (Машинный нуль) — числовое значение с таким отрицательным порядком, которое воспринимается машиной как ноль. Отличное от, но приближенное к 0 дробное число, что компьютер считает за 0, потому что из-за технических ограничений архитектуры не в силах отличить от 0.

Машинный эпсилон (англ. Machine epsilon) — числовое значение, меньше которого невозможно задавать относительную точность для любого алгоритма, возвращающего вещественные числа. Абсолютное значение «машинного эпсилон» зависит от разрядности сетки применяемой ЭВМ, типа (разрядности) используемых при расчетах чисел, и от принятой в конкретном трансляторе структуры представления вещественных чисел (количества бит, отводимых на мантиссу и на порядок). Формально машинный эпсилон обычно определяют как минимальное из чисел ε, для которого 1+ε>1 при машинных расчетах с числами данного типа. Альтернативное определение — максимальное ε, для которого справедливо равенство 1+ε=1.

Практическая важность машинного эпсилон связана с тем, что два (отличных от нуля) числа являются одинаковыми с точки зрения машинной арифметики, если их относительная разность по модулю меньше (при определении первого типа) или не превосходит (при определении второго типа) машинного эпсилон.

В ЯП

C

В ЯП C существуют предельные константы FLT_EPSILON, DBL_EPSILON и LDBL_EPSILON явл. «машинными эпсилон», соотв. 1-му определению: FLT_EPSILON = 2−23 ≈ 1.19e-07 — машинный эпсилон для чисел типа float (32 бита), DBL_EPSILON = 2−52 ≈ 2.20e-16 — для типа double (64 бита), и LDBL_EPSILON = 2−63 ≈ 1.08e-19 — для типа long double (80 бит). При альт. определении соотв. машинные эпсилон будут вдвое меньше: 2−24, 2−53 и 2−64. В некоторых компиляторах C (напр., gcc, Intel’s C/C++ compiler) допускается использование переменных четверной точности (_float128, _Quad). Соответствующие машинные эпсилон равны 2−112 ≈ 1.93e-34 и 2−113 ≈ 9.63e-35.

Примеры

C

Пример вычисления машинного эпсилона (не путать с машинным нулём) на ЯП C:

float macheps(void) {
	float e = 1.0f;
	while (1.0f + e / 2.0f > 1.0f)
		e /= 2.0f;
	return e;
}

C++

Пример на ЯП C++:

#include <iostream>
#include <stdint.h>
#include <iomanip>

template<typename float_t, typename int_t>
float_t machine_eps() {
	union {
		float_t f;
		int_t i;
	} one, one_plus, little, last_little;

	one.f = 1.0;
	little.f = 1.0;
	last_little.f = little.f;

	while (true) {
		one_plus.f = one.f;
		one_plus.f += little.f;

		if (one.i != one_plus.i) {
			last_little.f = little.f;
			little.f /= 2.0;
		} else {
			return last_little.f;
		}
	}
}

int main() {
	std::cout << "machine epsilon:\n";
	std::cout << "float: " << std::setprecision(18) << machine_eps<float, uint32_t>() << std::endl;
	std::cout << "double: " << std::setprecision(18) << machine_eps<double, uint64_t>() << std::endl;
}

Python

Пример на Python:

def machineEpsilon(func=float):
	machine_epsilon = func(1)
	while func(1)+func(machine_epsilon) != func(1):
		machine_epsilon_last = machine_epsilon
		machine_epsilon = func(machine_epsilon) / func(2)
	return machine_epsilon_last

Вывод может быть таким (с использованием IPython):

In [1]: machineEpsilon(int)
Out[1]: 1
In [2]: machineEpsilon(float)
Out[2]: 2.2204460492503131e-16
In [3]: machineEpsilon(complex)
Out[3]: (2.2204460492503131e-16+0j)