Arrotondamento a pari in C #
Domanda
Non vedo il risultato che mi aspetto con Math.Round.
return Math.Round(99.96535789, 2, MidpointRounding.ToEven); // returning 99.97
Come intendo MidpointRounding.ToEven, il 5 nella posizione millesimale dovrebbe far sì che l'output sia 99.96. Non è così?
Ho anche provato questo, ma ha restituito anche 99,97:
return Math.Round(99.96535789 * 100, MidpointRounding.ToEven)/100;
Cosa mi sto perdendo
Grazie!
Soluzione
In realtà non sei nel punto medio. MidpointRounding.ToEven
indica che se avessi il numero 99.965 , ovvero 99.96500000 [ecc.], quindi otterrai 99,96. Poiché il numero che stai passando a Math.Round è al di sopra di questo punto medio, si sta arrotondando per eccesso.
Se si desidera arrotondare il numero a 99,96, procedere come segue:
// this will round 99.965 down to 99.96
return Math.Round(Math.Truncate(99.96535789*1000)/1000, 2, MidpointRounding.ToEven);
E hey, ecco una piccola funzione utile per fare quanto sopra per i casi generali:
// This is meant to be cute;
// I take no responsibility for floating-point errors.
double TruncateThenRound(double value, int digits, MidpointRounding mode) {
double multiplier = Math.Pow(10.0, digits + 1);
double truncated = Math.Truncate(value * multiplier) / multiplier;
return Math.Round(truncated, digits, mode);
}
Altri suggerimenti
Arrotonda a 99,96 solo se ci si trova sul punto medio stesso, ovvero 99.965:
C:\temp>ipy IronPython 2.6 Beta 2 (2.6.0.20) on .NET 2.0.50727.4927 Type "help", "copyright", "credits" or "license" for more information. >>> import clr >>> from System import Math, MidpointRounding >>> Math.Round(99.9651, 2, MidpointRounding.ToEven) 99.97 >>> Math.Round(99.965, 2, MidpointRounding.ToEven) 99.96 >>> Math.Round(99.9649, 2, MidpointRounding.ToEven) 99.96 >>> Math.Round(99.975, 2, MidpointRounding.ToEven) 99.98 >>>
Il valore MidpointRounding
entra in gioco solo quando si tenta di arrotondare un valore la cui cifra meno significativa è esattamente 5. In altre parole, il valore dovrebbe essere 99.965
per ottenere il risultato desiderato. Dal momento che non è così, stai semplicemente osservando il meccanismo di arrotondamento standard. Vedi la pagina MSDN per maggiori informazioni.
Ecco i risultati che hanno fatto luce sull'argomento:
Math.Round(99.96535789, 2, MidpointRounding.ToEven); // returning 99.97
Math.Round(99.965, 2, MidpointRounding.ToEven); // returning 99.96
Math.Round(99.96500000, 2, MidpointRounding.ToEven); // returning 99.96
Il punto medio è esattamente 5 ... non 535789, non 499999.
L'arrotondamento del punto medio viene considerato solo se il valore è compreso tra due casi.
Nel tuo caso, non è " 5 " ;, è " 535 ... " ;, quindi è maggiore del punto medio e le routine a .96. Per ottenere il comportamento che ti aspetti, dovrai troncare al terzo punto decimale, POI arrotondato usando MidpointRounding.ToEven.
Math.Round 'Arrotonda un valore decimale a un numero specificato di cifre frazionarie.' quando si arrotondano 99.96500000,2 si arrotondano a 99.96 e 99.96500001 a 99.67. Arrotonda l'intero valore.
Se fossi in me, non userei Math.Round ()
, perché non è quello che stai cercando di realizzare.
Questo è quello che vorrei fare:
double num = 99.96535789;
double percentage = Math.Floor(100 * num) / 100;
Che è molto più facile da leggere ed è più un approccio matematico.
Moltiplico il numero per 100
, ora ho 9996.535789
.
Quindi pavimentalo, che è nettamente diverso dall'arrotondamento, per restituire il numero intero più piccolo più vicino al numero, per ottenere 9996
.
Divido quindi per 100
per ottenere il 99,96
richiesto.
P.S.
Floor è l'opposto di soffitto , che restituisce il numero intero più grande più vicino al numero.
Pertanto, il limite di 9996.535789
è 9997
.
Entrambi sono diversi dal arrotondamento senza punti decimali, il che in realtà restituisce il numero intero più vicino al numero, sia esso più piccolo o più grande, a seconda di quale sia il più vicino; ecco perché stavi ottenendo 99,97
quando hai usato arrotondamento .