La comparación de las cuestiones en DUnit CheckEquals con la Moneda de los Valores de Campo

StackOverflow https://stackoverflow.com/questions/488746

  •  20-08-2019
  •  | 
  •  

Pregunta

Estoy comparando algunos de los valores de moneda en DUnit pero no funciona en mi máquina (trabajo en otros, pero no en la mía).

Un ejemplo:

CheckEquals(16.65, SomeCurrencyFieldValue);

Plantea:

expected: <16,65> but was: <16,65>

si hacer la siguiente comparación, a continuación, funciona:

var
  Temp: Currency;
begin
  Temp := 16.65;
  CheckEquals(Temp, SomeCurrencyFieldValue);

La pregunta es:¿Por qué la comparación no funciona cuando se me pase el valor directo a la CheckEquals método?

¿Fue útil?

Solución

El problema tiene que ver con cómo Currency los valores se convierten en Extended los valores en tiempo de ejecución frente a cómo de punto flotante literales se convierten en Extended los valores en tiempo de compilación.Si la conversión no es el mismo en ambos casos, los valores pasan a CheckEquals no pueden comparar la igualdad.

Sería digno de la comprobación en el depurador de la CPU de la ventana si cualquiera de los valores pasa a través de un intermedio Double valor en su camino a Extended en la preparación para la llamada a la función.Una conversión adicional podría afectar el valor exacto del resultado.

Otra cosa a considerar es que 16.65 no es representable exactamente como un Extended valor, pero es puede representarse exactamente como un Currency valor.Aunque Currency se clasifica como un tipo de punto flotante, es realmente un punto fijo a escala entero de 64 bits.Probablemente ese sea el motivo para solicitar una nueva CheckEquals sobrecarga en DUnit que toma eso en cuenta.

Otros consejos

Veo que solo hay CheckEquals () para valores extendidos en las fuentes dUnit de Delphi 2007. Pero podrías usar este:

procedure CheckEquals(expected, actual: extended; delta: extended;
  msg: string = ''); overload; virtual;

y proporcione un delta apropiado para los valores de moneda.

Encontré el mismo problema. Parece que algunas DLL modifican una palabra de control de FPU (procesador). Esto explica por qué el error no ocurre siempre. Puede aparecer repentinamente cuando se agregan algunas pruebas nuevas, que usan otras unidades que el conjunto de pruebas anterior. O si una actualización de software instala archivos DLL incorrectos. He escrito sobre en mi blog:

También descubrí que Delphi contiene una función SafeLoadLibrary, que restaura la palabra de control.

Esto también explica por qué la pregunta original menciona que el problema depende de la máquina.

aquí hay una solución sugerida:

procedure CheckEquals(expected, actual: double; Precision:integer; msg:string ='');overload;virtual;

...

procedure TAbstractTest.CheckEquals(expected, actual: double;
  Precision: integer; msg: string);
var
  I: Integer;
begin
  FCheckCalled := true;
  for I := 0 to Precision do begin
    Expected := Expected * 10;
    Actual := Actual * 10;
  end;
  if Round(Expected) <> Round(Actual) then
    FailNotEquals( IntToStr(Round(Expected)), IntToStr(Round(Actual)), msg, CallerAddr);
end;

Sé que su implementación es mala, pero es solo una idea, que me gusta más que " delta " ;, y mucho más fácil de usar.

En la versión actual de dunit puede usar

procedure CheckEquals(expected, actual: extended; delta: extended; msg: string = ''); overload; virtual;
CheckEquals(0.011,0.01,0.009,'will pass');
Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top