Saltar al contenido

¿Cómo elegir el valor épsilon para punto flotante?

Solución:

Un valor de referencia para épsilon es la diferencia entre 1.0 y el siguiente valor representable más alto. En C ++, este valor está disponible como std::numeric_limits<T>::epsilon().

Tenga en cuenta que, como mínimo, debe escalar este valor como una proporción del número real que está probando. Además, dado que la precisión se escala solo aproximadamente con el valor numérico, es posible que desee aumentar su margen en un factor pequeño para evitar errores falsos:

double epsilon = std::numeric_limits<double>::epsilon();

// C++ literals and math functions are double by default
bool is_near = abs(0.1+0.2 - 0.3) <= 0.3 * (2*epsilon);

Como ejemplo más completo, una función para comparar dobles:

bool is_approximately_equal(double a, double b) {
  double scale = max(abs(a), abs(b));
  return abs(a - b) <= scale * (2*epsilon);
}

En la práctica, el valor real de épsilon que debe usar depende de lo que esté haciendo y del tipo de tolerancia que realmente necesite. Los algoritmos numéricos normalmente tendrán tolerancias de precisión (promedio y máximo), así como estimaciones de tiempo y espacio. Pero la estimación de precisión generalmente comienza con algo como characteristic_value * epsilon.

Puede estimar el épsilon de la máquina utilizando el algoritmo siguiente. Necesitas multiplicar este épsilon con el valor entero de 1+(log(number)/log(2)). Una vez que haya determinado este valor para todos los números en su ecuación, puede usar el análisis de errores para estimar el valor épsilon para un cálculo específico.

epsilon=1.0

while (1.0 + (epsilon/2.0) > 1.0) {
  epsilon = epsilon /2.0     
}
//Calculate error using error analysis for a + b
epsilon_equation=Math.sqrt(2*epsilon*epsilon)

document.write('Epsilon: ' + epsilon_equation+'<br>')
document.write('Floating point error: ' + Math.abs(0.2 + 0.4 -0.6)+'<br>')
document.write('Comparison using epsilon: ')
document.write(Math.abs(0.2 + 0.4 -0.6)<epsilon_equation)

Siguiendo su comentario, probé el mismo enfoque en C # y parece funcionar:

using System;

namespace ConsoleApplication
{
   
    public class Program
    {
        public static void Main(string[] args)
        {
            double epsilon = 1.0;

            while (1.0 + (epsilon/2.0) > 1.0)
            {
                epsilon = epsilon/2.0;
            }

            double epsilon_equation = Math.Sqrt(2*epsilon*epsilon);

            Console.WriteLine(Math.Abs(1.0 + 2.0 - 3.0) < Math.Sqrt(3.0 * epsilon_equation * epsilon_equation));
        }
    }
}
¡Haz clic para puntuar esta entrada!
(Votos: 0 Promedio: 0)



Utiliza Nuestro Buscador

Deja una respuesta

Tu dirección de correo electrónico no será publicada. Los campos obligatorios están marcados con *