Comparación entre reales
Artículo por Club Developers · 31 diciembre 2005
4390 vistas
Cuando comparamos 2 número de coma flotante con el operador =, podemos encontrarnos con muchas sorpresas: 2 números a priori iguales puede que no lo sean. Esto es por culpa de la representación del coma flotante, el cual es una aproximación del número y no una representación exacta. Por ejemplo:
Por suerte, a partir de Delphi 6, Borland nos provee de 3 funciones en la unidad Math:
Estas tres funciones están definidas para los tipos Single, Double y Extended. CompareValue también lo está para Integer y Int64.
Por lo tanto, el código anterior que no funcionaba quedará asÃ:
La ayuda de Delphi nos indica que Epsilon es la cantidad máxima en que A y B pueden diferir para considerarse iguales. Por defecto este valor es 0, pero mirando el código, constatamos que si Epsilon es 0 (cosa que no tendrÃa sentido), el valor es corregido.
Si tenemos una versión anterior a Delphi 6
Tendremos que escribir unas funciones que haga este trabajo
delphi
var  a: double; begin  a := 11 + 1.11;  if (a = 12.11) then   showMessage('igual')  else   showMessage('no igual') // <-- mostrará este mensaje end;
Por suerte, a partir de Delphi 6, Borland nos provee de 3 funciones en la unidad Math:
delphi
// indica si 2 valores en coma flotante son (aproximádamente) iguales. function SameValue(const A, B: Single; Epsilon: Single = 0): Boolean; overload; // Las 2 siguientes usan SameValue : // Indica si una variable o una expresión en coma flotante es 0 o un valor próximo a 0. function IsZero(const A: Single; Epsilon: Single = 0): Boolean; overload; // Devuelve la relación entre dos valores numéricos. function CompareValue(const A, B: Single; Epsilon: Single = 0): TValueRelationship; overload;
Estas tres funciones están definidas para los tipos Single, Double y Extended. CompareValue también lo está para Integer y Int64.
Por lo tanto, el código anterior que no funcionaba quedará asÃ:
delphi
uses Math; var  a : double; begin  a := 11 + 1.11;  if SameValue(a, 12.11) then   ShowMessage('igual')   // <-- mostrará este mensaje  else   ShowMessage('no igual'); end;
La ayuda de Delphi nos indica que Epsilon es la cantidad máxima en que A y B pueden diferir para considerarse iguales. Por defecto este valor es 0, pero mirando el código, constatamos que si Epsilon es 0 (cosa que no tendrÃa sentido), el valor es corregido.
Si tenemos una versión anterior a Delphi 6
Tendremos que escribir unas funciones que haga este trabajo
delphi
function RealesIguales(n1,n2 : extended) : boolean; begin  Result := Abs(n1 - n2) < Min(abs(n1), abs(n2)) * 1E-16; end; function RealesIguales(n1,n2 : double) : boolean; begin  Result := Abs(n1 - n2) < Min(abs(n1), abs(n2)) * 1E-12; end; function RealesIguales(n1,n2 : single) : boolean; begin  Result := Abs(n1 - n2) < Min(abs(n1), abs(n2)) * 1E-4; end;