2009-10-30 26 views

Respuesta

44

Realmente no puede comparar valores flotantes e integrales de una manera ingenua; particularmente, ya que está el clásico floating pointrepresentation challenges. Lo que puede hacer es restar uno del otro y ver si la diferencia entre ellos es menor de cierta precisión que te importa, de este modo:

int iValue = 0; 
double dValue = 0.0; 

var diff = Math.Abs(dvalue - iValue); 
if(diff < 0.0000001) // need some min threshold to compare floating points 
    return true; // items equal 

Usted realmente tiene que definir por sí mismo lo equality significa para usted . Por ejemplo, es posible que desee un valor de coma flotante para redondear hacia el entero más cercano, de modo que 3.999999981 sea "igual" a 4. O tal vez desee truncar el valor, por lo que sería 3. Depende de lo que estamos tratando de lograr.

EDIT: Tenga en cuenta que he elegido 0,0000001 como un valor umbral de ejemplo ... tiene que decidir por sí mismo qué precisión es suficiente para la comparación. Solo tenga en cuenta que necesita estar dentro de los límites de representación normales de double que creo que se define como Double.Espilon.

+0

Esta es una buena solución al problema que mencioné. Para mayor precisión (solo cuando sea necesario), use solo enteros, como sugerí en mi respuesta. –

+0

¿Sería mejor comparar con el epsilon constante definido por el sistema (consulte aquí http://msdn.microsoft.com/en-us/library/system.double.epsilon.aspx) en lugar de un valor codificado como 0.0000001? NB Nunca he codificado C# (solo C++), pero supongo que se aplica el mismo principio – pxb

+1

Lo menciono en la edición de mi respuesta. Epsilon puede o no ser una buena opción dependiendo de la precisión que le interese a OP en su código. – LBushkin

1

Esto realmente depende de lo que considera "igual". Si desea que su comparación para volver verdadero si y sólo si el doble coincide exactamente con el valor entero (es decir, no tiene un componente fraccional), que debe emitir su int a un doble para hacer la comparación:

bool isEqual = (double)iValue == dValue; 

Si algo como 1.1 se consideraría igual a 1, puede lanzar el doble a un int (si quiere ignorar por completo el componente fraccionario) o redondear el doble si quiere decir 1.9 a igual 2.

+0

Cuidado con el redondeo, sin embargo. Mucha gente parece sorprendida cuando 2.5 rondas a 2. – Joey

+0

@Joey Es bastante trivial escribir su propio código de redondeo para tener el comportamiento que desea si los tres integrados no satisfacen sus necesidades. – Casey

3

Es una idea extremadamente mala para comparar números enteros y números de coma flotante para la igualdad en cualquier idioma. Funciona para casos muy simples, pero después de hacer algunos cálculos, la probabilidad de que el programa haga lo que usted quiere disminuye drásticamente.

Tiene que ver con la manera en que se almacenan los números de coma flotante en un sistema digital binario.

Si está seguro de que quiere usar esto, cree una clase para hacer su propio número con fracciones. use one int para mantener el número entero, y otro int para mantener la fracción.

0

Hoy en día, casi la única vez que uno debería ser la comparación de valores de tipos double y, o bien integer o long para la igualdad estricta es cuando, por alguna razón, se trata de almacenamiento atascado o que pasa cantidades integrales como valores de punto flotante y necesidades posteriores para convertirlos de vuelta. En la mayoría de los casos, dicha conversión se puede realizar más fácilmente al convertir el tipo integral en double, y luego comparar el resultado de ese modelo. Tenga en cuenta que la conversión de long a double puede ser imprecisa si el número está fuera del rango ± 2 . No obstante, en los días previos a la disponibilidad de long de 64 bits, double era un tipo de almacenamiento útil para cantidades enteras que eran demasiado grandes para un int de 32 bits pero lo suficientemente pequeño para ser manejado por double.

Tenga en cuenta que la conversión de un long a double y luego hacer la comparación producirá un "igual" número si el valor nominal de la double no coincide con precisión el valor long, sino que representa el más cercano posible double a ese valor. Este comportamiento tiene sentido si se reconoce que los tipos de punto flotante no representan un solo valor preciso, sino un rango de valores.

2
double val1 = 0; 
double val2 = 0.0; 
if((val1 - Double.Epsilon) < 0) 
{ 
    // Put your code here 
} 

     OR 

if((val2 - Double.Epsilon) < 0) 
{ 
    // Put your code here 
} 

donde Double.Epsilon es el valor más bajo posible para Double.

Cuestiones relacionadas