Perché questo test xUnit fallire?
-
01-10-2019 - |
Domanda
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
Soluzione
Con il diverso ordine delle operazioni, il punto binario galleggianti appaiono errori di arrotondamento da propaga in modo diverso. È possibile ottenere "meno sorprendenti", ma potenzialmente più lente risultati con il tipo decimale.
3.2 * 1.0 / (1.0 / 1.000.000,0) -> 3.200.000,0000,000005 millions
(try (3.2 * 1.0 / (1.0 / 1000000.0) ).ToString("R");
3,2 * (1.0 / (1.0 / 1.000.000,0)) -> 3.200.000,0
Se non si dispone già capire le differenze tra floating tipi di punti e decimali, si prega di leggere: http://docs.sun.com/source/806-3568/ncg_goldberg.html
In alternativa, se preferite qualcosa di più semplice in inglese: http://floating-point-gui.de/
Altri suggerimenti
Yoe non può vedere dal snippet di codice, ma sono abbastanza sicuro che ha qualcosa a che fare con il fatto che le tue prime linee (quelle che passano) hanno un .0
, mentre quello in mancanza ha qualcosa di diverso da zero dopo la virgola.
Sono sicuro che c'è qualcosa di strano, come 3.2000000001
venire da qualche parte. Forse dal database?
HTH!
Thomas