C'è un modo per fare 'corretto' arrotondamento aritmetico in .NET? / C #
-
22-09-2019 - |
Domanda
Sto cercando di arrotondare un numero al suo primo decimale e, considerando le diverse opzioni MidpointRounding, che sembra funzionare bene. Un problema sorge però quando il numero è sunsequent decimale che aritmeticamente influenzare l'arrotondamento.
Un esempio:
Con 0.1
, 0.11..0.19
e 0.141..0.44
funziona:
Math.Round(0.1, 1) == 0.1
Math.Round(0.11, 1) == 0.1
Math.Round(0.14, 1) == 0.1
Math.Round(0.15, 1) == 0.2
Math.Round(0.141, 1) == 0.1
Ma con 0.141..0.149
ritorna sempre 0.1
, anche se 0.146..0.149
deve arrotondare a 0.2
:
Math.Round(0.145, 1, MidpointRounding.AwayFromZero) == 0.1
Math.Round(0.146, 1, MidpointRounding.AwayFromZero) == 0.1
Math.Round(0.146, 1, MidpointRounding.ToEven) == 0.1
Math.Round(0.146M, 1, MidpointRounding.ToEven) == 0.1M
Math.Round(0.146M, 1, MidpointRounding.AwayFromZero) == 0.1M
Ho cercato di trovare una funzione che risolve questo problema, e funziona bene per questo caso, ma naturalmente viene a mancare glamour se si tenta di arrotondare cioè 0.144449
alla sua prima cifra decimale (che dovrebbe essere 0.2
, ma i risultati 0.1
.) (Questo non funziona con Math.round () o.)
private double "round"(double value, int digit)
{
// basically the old "add 0.5, then truncate to integer" trick
double fix = 0.5D/( Math.Pow(10D, digit+1) )*( value >= 0 ? 1D : -1D );
double fixedValue = value + fix;
// 'truncate to integer' - shift left, round, shift right
return Math.Round(fixedValue * Math.Pow(10D, digit)) / Math.Pow(10D, digit);
}
presumo una soluzione potrebbe essere quella di elencare tutte le cifre, trovare il primo valore maggiore di 4 e poi radunare, altrimenti rotonda verso il basso. Problema 1: Che sembra stupido, Problema 2: Non ho idea di come enumerare le cifre senza un trilione di moltiplicazioni e subtractios
.Per farla breve:? Qual è il modo migliore per farlo
Soluzione
Math.Round()
si sta comportando in modo corretto.
Al momento di eseguire l'arrotondamento punto medio standard, è mai bisogno di guardare oltre 1 cifra decimale al di là di dove si sta arrotondando al. Se si sono arrotondamento al più vicino decimo, allora non hai mai bisogno di guardare al di là della seconda cifra dopo la virgola.
L'idea con arrotondamento punto centrale è che la metà della a-tra numeri devono arrotondare e mezzo dovrebbero arrotondare. Quindi, per i numeri tra 0,1 e 0,2, la metà di loro deve arrotondare a 0,1 e la metà deve arrotondare a 0,2. Il punto medio tra questi due numeri è 0,15, in modo che è la soglia per arrotondamento. 0.146 è inferiore a 0,15, quindi deve arrotondare a 0,1.
Midpoint
0.10 0.15 0.20
|----------------|----|---------------------|
0.146
<---- Rounds Down
Altri suggerimenti
Non capisco quello che si sta cercando di realizzare qui. 0,149 arrotondato al primo decimale è 0.1, non 0.2
L'arrotondamento non è un processo iterativo, si arrotonda solo una volta.
0,146 arrotondato a 1 cifra decimale è 0.1.
Non si fa in questo modo:
0.146 --> 0.15
0.15 --> 0.2
È solo fare questo:
0.146 --> 0.1
In caso contrario, il seguente:
0.14444444444444446
sarebbe anche intorno a 0.2, ma non è così, e non dovrebbe.
Non cercare di complicare il 'errori' di arrotondamento. Che è quello che stai cercando di fare.
0,146 dovrebbe rotonda fino a 0,1 se si sta andando a posto un decimale.
Con l'arrotondamento a 0,15 prima, poi di nuovo a 0,2 Sei solo introducendo una maggiore errore di arrotondamento, non di meno.