2012-01-22 26 views
6

Estoy tratando de comparar una matriz de dobles a un doble escalar para la igualdad, pero la igualdad nunca se reconoce bajo ciertas circunstancias. Sospecho que esto tiene que ver con la forma en que se representa el doble (por ejemplo, 1.0 vs 1.00), pero no puedo resolverlo.comparación doble de matlab

Por ejemplo, he generado una matriz compuesta de miles de valores dobles, el último pocos de los cuales en algún instante de tiempo se dan por

10.6000 
-11.0000 
10.2000 
22.6000 
3.4000 

Si comprobar la igualdad de 10.2 (o 10.2000) por el comando array==10.2 (o array=10.2000), devuelvo una matriz de 0. Si coloco los valores que se muestran en una matriz manualmente (por ejemplo, array=[10.6000 -11.0000 10.2000 22.6000 3.4000]), el comando es exitoso (es decir, array==10.2 devuelve 0 0 1 0 0). ¿Podría alguien explicar por qué la igualdad tiene éxito si ingreso los valores manualmente, pero falla si la matriz se genera en el contexto de un programa? Puedo rectificar el error de comparación utilizando una comparación aproximada en lugar de una exacta (por ejemplo, (array<10.20001) & (array>10.19999)), pero esto parece insatisfactorio.

Editar: Los valores en la matriz se generan mediante la suma o resta iterativa de un doble constante (por ejemplo, 0.2). El módulo de este conjunto por 0.2 debe estar por lo tanto en todas partes igual a 0. De hecho, el módulo de cada elemento es igual a cualquiera de 0 o 0.2, como se muestra a continuación para la secuencia anterior de los números en la matriz:

mod(array,0.2) 
... 
0.2000 
    0 
0.2000 
0.2000 
    0 

De nuevo, si los valores se colocan en una matriz de forma manual y el módulo se toma, se obtiene el valor esperado de todos 0 s.

Respuesta

6

La razón es que MATLAB truncó los números en la matriz para conservar solo 4 dígitos después del punto decimal cuando se visualiza. Es decir, el valor real de su matriz puede ser [10.600000000001, -10.99999999999, ...]. Tiene razón, esto se debe a la representación interna de los números de coma flotante en la computadora, lo que puede ocasionar pequeños errores en los cálculos.

Personalmente, creo que hay dos soluciones, una es aproximada como usted, mientras que la otra es redondear la matriz primero (por ejemplo, con this tool de FileExchange), y luego hacer la coincidencia exacta.

+0

Muy útil. Una pregunta de seguimiento es que mis números se generaron sumando o restando una cantidad constante (por ej., '0.2') durante muchos ciclos en un bucle, así que matemáticamente los números en la matriz deberían ser 0 cuando el módulo 0.2 (' mod (matriz) , 0.2) ') se aplica. De hecho, ellos no lo son. Son iguales a 0 o 0.2. Sin embargo, por supuesto, cuando aplico el módulo 0.2 a cualquiera de los números en la matriz escribiéndolos manualmente, se da el valor esperado de 0. ¿Podrías explicar este comportamiento? ¡Gracias! – user001

+1

Esto implica cómo se representan los números de coma flotante en las computadoras. Un hecho bien conocido es que las computadoras usan binario en lugar de decimal. Sin embargo, hay un problema con el binario, es decir, una fracción finita, digamos que 0,2 en decimal no se puede representar con dígitos finitos en binario. Es decir, la representación binaria de 0.2 en la computadora es en realidad 0.001110011100111 ..., que es interminable. Sin embargo, MATLAB usa 64 bits para representar un 'Single', que puede causar 2^(- 65) error. Este error es bastante pequeño, pero cuando hay bastantes iteraciones, puede acumularse. – grapeot

+0

Maravillosa explicación. Muchas gracias. – user001

2

Algo probablemente esté en una sola precisión en alguna parte, y doble en otros lugares. La representación binaria de, p. 10.2 en cada uno es diferente ya que terminan después de un número diferente de bits. Por lo tanto son diferentes:

>> if (single(10.2) == 10.2) disp('honk'); end 
>> if (single(10.2) == single(10.2)) disp('honk'); end 
honk 

Tendrá que comprobar la igualdad dentro de alguna pequeña diferencia:

eps = 0.001; 
result = abs(array-10.2) < eps; 

Puede encontrar la precisión utilizado en una matriz mediante whos:

>> whos A 
    Name  Size   Bytes Class  Attributes 

    A   1x2     8 single  
+0

Gracias @Alex. ¿Podrían ver mi comentario debajo de la publicación de grapeot? Si tomo mi matriz, generada por una serie de suma o resta de 0.2 (doble) en el contexto de un ciclo, el módulo de cada elemento en la matriz es 0 o 0.2, lo que no tiene sentido. Comprobé la precisión de mi matriz usando el comando 'whos' (gracias), y es doble, al igual que mi variable de comparación escalar. – user001

+1

0.2 no se puede representar exactamente como un flotador binaria (ver http://www.h-schmidt.net/FloatApplet/IEEE754.html), que es una fracción continua 0,1001 [1001 ...]. Entonces, agregar 0.2 a algo podría no hacer exactamente lo que piensas. Si la exactitud es importante, trabaje en las unidades mínimas de su problema, en este caso probablemente sea más fácil trabajar a 10x, y agregue 2 a números, luego marque mod (num, 2), luego dévide por 10 al final. – Alex

+0

Muchas gracias. El problema se resuelve sumando/restando 0.25, y esto tiene sentido porque 0.25 se puede representar exactamente como un flotador binario de acuerdo con el applet que proporcionó. Supongo que el mejor lugar para encontrar más información sería un artículo sobre la representación de números en coma flotante. – user001

1

Cree un archivo de función MATLAB que acepte los valores de un módulo (de 3 a 9; es decir, de Z3 a Z9) y generará el menor valor posible descrito por las condiciones del módulo.

Simulación de la muestra:

Z = [3 4 5]; % Modulo Z3, Z4, Z5 y

r = [2 1 4]; % El resto Valores

menos valor posible es 29.

Las entradas Z debe ser una matriz array ... donde en puede escribir cualquier número de 3 a 9 .... y usted puede escriba 3,4,5,6,7,8,9 en cualquier orden, en cualquier emparejamientos o agrupaciones ...

las entradas R debe ser igual al número de entradas z también ...

la salida debería producir el menor valor posible aunque las condiciones del módulo ...

Cuestiones relacionadas