¿Por qué falla esta prueba xUnit?
-
01-10-2019 - |
Pregunta
Assert.Equal(1000000.0, table.Convert("g", "mcg", 1.0)); // Pass
Assert.Equal(2000000.0, table.Convert("g", "mcg", 2.0)); // Pass
Assert.Equal(3200000.0, table.Convert("g", "mcg", 3.2)); // Fail
// The failing one is equal to doing the following calculation, which fails also:
Assert.Equal(3200000.0, 3.2 * 1.0 / (1.0 / 1000000.0)); // Fail
Assert.Equal(3200000.0, 3.2 * (1.0 / (1.0 / 1000000.0)));// Pass, WTF?!?!
===================================================================
Assert.Equal() Failure
Expected: 3200000
Actual: 3200000
Solución
Con la diferente orden de las operaciones, el binario de coma flotante aparecen errores de redondeo que se propaga de manera diferente. Usted puede conseguir "menos sorprendentes", pero potencialmente más lentos resultados con el tipo Decimal.
3,2 * 1,0 / (1,0 / 1000000.0) -> 3,200,000.0000000005
(try (3.2 * 1.0 / (1.0 / 1000000.0) ).ToString("R");
3,2 * (1,0 / (1,0 / 1000000.0)) -> 3200000.0
Si usted no tiene ya entender las diferencias entre los tipos de punto decimal flotante y, por favor, lea: http://docs.sun.com/source/806-3568/ncg_goldberg.html
O, si se prefiere algo más claro en Inglés: http://floating-point-gui.de/
Otros consejos
Yoe no puede verlo desde el fragmento de código, pero estoy bastante seguro de que tiene algo que ver con el hecho de que sus primeras líneas (los que pasan a) tener un .0
, mientras que el fallido tiene algo desigual a cero después de la coma.
Estoy seguro de que hay algo extraño como 3.2000000001
venir en alguna parte. Tal vez a partir de la base de datos?
HTH
Thomas