Pregunta

Estoy escribiendo un programa en el que debo eliminar duplicados de puntos almacenados en una matriz.El problema es que cuando se trata de comprobar si los puntos están en la matriz, MATLAB no puede reconocer en la matriz a pesar de que existen.

En el código siguiente, intersections la función obtiene los puntos de intersección:

[points(:,1), points(:,2)] = intersections(...
    obj.modifiedVGVertices(1,:), obj.modifiedVGVertices(2,:), ...
    [vertex1(1) vertex2(1)], [vertex1(2) vertex2(2)]);

El resultado:

>> points
points =
   12.0000   15.0000
   33.0000   24.0000
   33.0000   24.0000

>> vertex1
vertex1 =
    12
    15

>> vertex2    
vertex2 =
    33
    24

Dos puntos (vertex1 y vertex2) debe ser eliminado del resultado.Debe ser hecho por los siguiente comandos:

points = points((points(:,1) ~= vertex1(1)) | (points(:,2) ~= vertex1(2)), :);
points = points((points(:,1) ~= vertex2(1)) | (points(:,2) ~= vertex2(2)), :);

Después de hacer eso, tenemos este resultado inesperado:

>> points
points =
   33.0000   24.0000

El resultado debe ser una matriz vacía.Como se puede ver, la primera (o la segunda?) par de [33.0000 24.0000] ha sido eliminado, pero no la segunda.

Luego he comprobado que estas dos expresiones:

>> points(1) ~= vertex2(1)
ans =
     0
>> points(2) ~= vertex2(2)
ans =
     1   % <-- It means 24.0000 is not equal to 24.0000?

¿Cuál es el problema?


Más sorprendentemente, he hecho un nuevo script que sólo tiene estos comandos:

points = [12.0000   15.0000
          33.0000   24.0000
          33.0000   24.0000];

vertex1 = [12 ;  15];
vertex2 = [33 ;  24];

points = points((points(:,1) ~= vertex1(1)) | (points(:,2) ~= vertex1(2)), :);
points = points((points(:,1) ~= vertex2(1)) | (points(:,2) ~= vertex2(2)), :);

El resultado como se esperaba:

>> points
points =  
   Empty matrix: 0-by-2
¿Fue útil?

Solución

El problema que tienes se refiere a cómo los números de punto flotante están representados en un equipo.Una discusión más detallada de punto flotante representaciones aparece hacia el final de mi respuesta (La "representación de punto Flotante" de la sección).El TL;DR versión:debido a que los equipos han finito de cantidades de memoria, los números sólo pueden ser representados con precisión finita.Por lo tanto, la exactitud de los números de punto flotante se limita a un determinado número de lugares decimales (cerca de 16 dígitos significativos para valores de precisión doble, el valor predeterminado utilizado en MATLAB).

Real vsmuestra precisión

Ahora, para abordar el ejemplo específico de la pregunta... mientras 24.0000 y 24.0000 son muestra de la misma manera, resulta que en realidad se diferencian por muy pequeñas cantidades decimales en este caso.No lo veo porque MATLAB sólo muestra 4 dígitos significativos por defecto, manteniendo el total de la pantalla limpia y ordenada. Si desea ver toda la precisión, debe emitir el format long comando o ver un representación hexadecimal de la serie:

>> pi
ans =
    3.1416
>> format long
>> pi
ans =
   3.141592653589793
>> num2hex(pi)
ans =
400921fb54442d18

Inicializa los valores de vslos valores calculados

Dado que sólo hay un número finito de valores que pueden ser representados por un número de punto flotante, es posible que en el cálculo del resultado en un valor que se encuentre entre dos de estas representaciones.En tal caso, el resultado tiene que ser redondeado a uno de ellos.Esto introduce un pequeño máquina de la precisión de error.Esto también significa que la inicialización de un valor directamente o a través de algún cálculo puede dar resultados ligeramente diferentes.Por ejemplo, el valor 0.1 no tiene un exacto representación de punto flotante (es decir,se pone ligeramente redondeado), y por lo que terminan con resultados inesperados como este debido a la forma en que los errores de redondeo se acumulan:

>> a=sum([0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1 0.1]);  % Sum 10 0.1s
>> b=1;                                               % Initialize to 1
>> a == b
ans =
  logical
   0                % They are unequal!
>> num2hex(a)       % Let's check their hex representation to confirm
ans =
3fefffffffffffff
>> num2hex(b)
ans =
3ff0000000000000

Cómo manejar correctamente de punto flotante comparaciones

Dado que los valores de punto flotante pueden diferir en cantidades muy pequeñas, las comparaciones deben hacerse comprobando que los valores están dentro de un rango (es decir,la tolerancia) de uno a otro, como opuesto exactamente igual a la otra.Por ejemplo:

a = 24;
b = 24.000001;
tolerance = 0.001;
if abs(a-b) < tolerance, disp('Equal!'); end

se mostrará "de la Igualdad!".

Entonces, usted puede cambiar su código para algo como:

points = points((abs(points(:,1)-vertex1(1)) > tolerance) | ...
                (abs(points(:,2)-vertex1(2)) > tolerance),:)

Representación de punto flotante

Un buen resumen de los números de punto flotante (y, específicamente, el Estándar IEEE 754 para la aritmética de punto flotante) es Lo Que Cada Equipo Científico Debe Saber Sobre La Aritmética De Punto Flotante por David Goldberg.

Un binario número de punto flotante en realidad es representado por tres enteros:un bit de signo s, una mantisa (o coeficiente de/fracción) b, y un exponente e. Para doble precisión de punto flotante de formato, cada número está representado por el de 64 bits establecidos en la memoria de la siguiente manera:

enter image description here

El valor real se puede encontrar con la siguiente fórmula:

enter image description here

Este formato permite que el número de representaciones en el rango de 10^-308 a 10^308.Para MATLAB puede obtener estos límites de realmin y realmax:

>> realmin
ans =
    2.225073858507201e-308
>> realmax
ans =
    1.797693134862316e+308

Puesto que hay un número finito de bits utilizados para representar un número en punto flotante, hay tan sólo una cantidad finita de números que pueden ser representados en el rango.Los cálculos frecuentemente resultan en un valor que no coincide exactamente con uno de estos finitos representaciones, por lo que los valores deben ser redondeados.Estos la máquina de los errores de precisión se hacen evidentes en diferentes maneras, como se describe en los ejemplos anteriores.

Para entender mejor estos errores de redondeo es útil observar la relación de punto flotante de precisión proporcionada por la función eps, en el que se cuantifica la distancia de un número dado a la mayor representación de punto flotante:

>> eps(1)
ans =
     2.220446049250313e-16
>> eps(1000)
ans =
     1.136868377216160e-13

Observe que la precisión es relativa para el tamaño de un número determinado a ser representado.los números más grandes tendrán grandes distancias entre punto flotante de representaciones, y por lo tanto tiene menos dígitos de precisión tras el punto decimal.Esto puede ser una consideración importante con algunos cálculos.Considere el siguiente ejemplo:

>> format long              % Display full precision
>> x = rand(1, 10);         % Get 10 random values between 0 and 1
>> a = mean(x)              % Take the mean
a =
   0.587307428244141
>> b = mean(x+10000)-10000  % Take the mean at a different scale, then shift back
b =
   0.587307428244458

Tenga en cuenta que cuando cambiamos los valores de x de la gama [0 1] para el rango de [10000 10001], calcular una media, luego restar la media de desplazamiento para la comparación, se obtiene un valor que es diferente para los últimos 3 dígitos significativos.Esto ilustra cómo un desplazamiento o la ampliación de los datos puede cambiar la exactitud de los cálculos realizados en el mismo, que es algo que tiene que ser explicada con ciertos problemas.

Otros consejos

vistazo a este artículo: Los peligros de punto flotante . A pesar de sus ejemplos están en FORTRAN que tiene sentido para prácticamente cualquier lenguaje de programación moderno, incluyendo MATLAB. Su problema (y solución para ello) se describe en la sección "Las comparaciones seguras".

type

format long g

Este comando mostrará el valor total del número. Es probable que sea algo así como 24.00000021321! = 24,00000123124

Trate de escribir

  

0,1 + 0,1 + 0,1 == 0.3.

Advertencia: Usted puede ser sorprendido por el resultado

Tal vez los dos números son realmente 24.0 y 24.000000001 pero no están viendo todas las cifras decimales.

Consulte el Matlab función EPS .

Matlab utiliza matemáticas de punto flotante hasta 16 dígitos de precisión (sólo se muestran 5).

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top