To właściwie funkcja. Zobacz <a href=" msdn.microsoft.com/en-us/library/… Dokumentacja MSDN</a> . Ten rodzaj zaokrąglania jest znany jako zaokrąglanie bankiera. Jeśli chodzi o obejście, istnieje <a href = " msdn. microsoft.com/en-us/library/... przeciążenie </a>, które pozwala dzwoniącemu na określenie sposobu zaokrąglania.
Joe
1
Najwyraźniej metoda okrągłe, gdy zostanie poproszona o zaokrąglenie liczby dokładnie między dwiema liczbami całkowitymi, zwraca parzystą liczbę całkowitą. Zatem Math.Round (3.5) zwraca 4. Zobacz ten artykuł
SQL Server zaokrągla w ten sposób; ciekawe wyniki testu, gdy istnieje test Ci jednostki ti sprawdzający zaokrąglenie wykonane w T-SQL.
idstam
7
@amed to nie jest błąd. Tak działa binarne zmiennoprzecinkowe. 1.005nie może być dokładnie reprezentowany podwójnie. To pewnie 1.00499.... Jeśli użyjesz Decimaltego problemu, zniknie. Istnienie przeciążenia Math.Round, które wymaga podwójnej liczby cyfr dziesiętnych, jest wątpliwym wyborem IMO, ponieważ rzadko działa w znaczący sposób.
CodesInChaos
Odpowiedzi:
560
Po pierwsze, i tak nie byłby to błąd C # - byłby to błąd .NET. C # to język - nie decyduje o sposobie Math.Roundimplementacji.
Po drugie, nie - jeśli przeczytasz dokumenty , zobaczysz, że domyślne zaokrąglenie to „zaokrąglenie do parzystego” (zaokrąglenie bankiera):
Zwracana wartość Typ: System.Double Liczba całkowita najbliższa a. Jeśli ułamkowa część a znajduje się w połowie drogi między dwiema liczbami całkowitymi, z których jedna jest parzysta, a druga nieparzysta, zwracana jest liczba parzysta. Zauważ, że ta metoda zwraca Doublezamiast typu całkowego.
Uwagi Zachowanie tej metody jest zgodne z normą IEEE 754, sekcja 4. Ten rodzaj zaokrąglania jest czasem nazywany zaokrąglaniem do najbliższego lub zaokrąglaniem bankierskim. Minimalizuje błędy zaokrąglania wynikające z konsekwentnego zaokrąglania wartości punktu środkowego w jednym kierunku.
Możesz określić, jak Math.Roundzaokrąglić punkty środkowe, używając przeciążenia, które przyjmuje MidpointRoundingwartość. Jest jedno przeciążenie MidpointRoundingodpowiadające każdemu z przeciążeń, które go nie ma:
To, czy to ustawienie domyślne zostało dobrze wybrane, czy nie, to inna sprawa. ( MidpointRoundingzostał wprowadzony tylko w .NET 2.0. Do tego czasu nie jestem pewien, czy istniał jakiś łatwy sposób na wdrożenie pożądanego zachowania bez robienia tego sam.) W szczególności historia pokazała, że nie jest to oczekiwane zachowanie - i w większości przypadków jest to grzech główny w projekcie API. Rozumiem, dlaczego zaokrąglanie za pomocą bankiera jest przydatne ... ale dla wielu wciąż jest zaskoczeniem.
Być może zainteresuje Cię najbliższa enum Java (enum RoundingMode), która oferuje jeszcze więcej opcji. (Nie dotyczy to tylko punktów środkowych).
nie wiem, czy to błąd, myślę, że to był projekt, ponieważ .5 jest tak blisko najbliższej najniższej liczby całkowitej, jak i najbliższej najwyższej liczby całkowitej.
Stan R.,
3
Pamiętam to zachowanie w VB przed zastosowaniem .NET.
John Fiala
7
Rzeczywiście, IEEE Standard 754, sekcja 4, jak stanowi dokumentacja.
Jon Skeet
2
Już dawno temu to mnie poparzyło i pomyślałem, że to też zwykła obłęd. Na szczęście dodali sposób na określenie zaokrąglenia, którego wszyscy nauczyliśmy się w szkole podstawowej; MidPointRounding.
Shea
26
+1 za „to nie jest oczekiwane zachowanie [...] to
główny
215
Nazywa się to zaokrąglaniem do parzystego (lub zaokrąglania bankowego), co jest prawidłową strategią zaokrąglania w celu minimalizacji narastających błędów sum (MidpointRounding.ToEven). Teoria jest taka, że jeśli zawsze zaokrąglasz liczbę 0,5 w tym samym kierunku, błędy będą narastały szybciej (zaokrąglanie do parzystej ma to zminimalizować) (a) .
Skorzystaj z tych linków, aby uzyskać opisy MSDN:
Math.Floor, który zaokrągla w dół w kierunku ujemnej nieskończoności.
Math.Ceiling, który zaokrągla w górę w kierunku dodatniej nieskończoności.
Math.Truncate, który zaokrągla w górę lub w dół w kierunku zera.
Math.Round, który zaokrągla do najbliższej liczby całkowitej lub określonej liczby miejsc dziesiętnych. Możesz określić zachowanie, jeśli jest dokładnie w jednakowej odległości między dwiema możliwościami, takimi jak zaokrąglanie, tak aby ostatnia cyfra była parzysta („ Round(2.5,MidpointRounding.ToEven)” staje się 2) lub tak, że jest dalej od zera („ Round(2.5,MidpointRounding.AwayFromZero)” staje się 3).
Poniższy schemat i tabela mogą pomóc:
-3-2-10123+--|------+---------+----|----+--|------+----|----+-------|-+
a b c d e
a=-2.7 b=-0.5 c=0.3 d=1.5 e=2.8===========================Floor-3-1012Ceiling-20123Truncate-20012Round(ToEven)-30023Round(AwayFromZero)-3-1023
Zauważ, że Roundjest o wiele potężniejszy niż się wydaje, po prostu dlatego, że może zaokrąglać do określonej liczby miejsc po przecinku. Wszystkie pozostałe zawsze zaokrąglają do dziesiętnych. Na przykład:
n =3.145;
a =System.Math.Round(n,2,MidpointRounding.ToEven);// 3.14
b =System.Math.Round(n,2,MidpointRounding.AwayFromZero);// 3.15
W przypadku innych funkcji musisz użyć funkcji zwielokrotniania / dzielenia, aby osiągnąć ten sam efekt:
c =System.Math.Truncate(n *100)/100;// 3.14
d =System.Math.Ceiling(n *100)/100;// 3.15
(a) Oczywiście, teoria ta zależy od tego, że twoje dane mają dość równomierny rozkład wartości na parzyste połowy (0,5, 2,5, 4,5, ...) i nieparzyste połowy (1,5, 3,5, ...).
Jeśli wszystkie „pół-wartości” są równe (na przykład), błędy będą kumulować się tak szybko, jakbyś zawsze zaokrąglał w górę.
Dobre wytłumaczenie! Chciałem zobaczyć na własne oczy, w jaki sposób kumuluje się błąd, i napisałem skrypt, który pokazuje, że wartości zaokrąglone za pomocą zaokrąglenia bankowego na dłuższą metę mają swoje sumy i średnie wartości znacznie bliższe wartościom pierwotnym. github.com/AmadeusW/RoundingDemo (zdjęcia dostępnych działek)
Amadeusz Wieczorek
Krótko po tym: czy etykać (= 2.8) nie powinno być dalej, niż 2tyka?
superjos,
Prosty sposób na zapamiętanie, przy założeniu, że dziesiąte miejsce to 5: - wszystkie miejsca i dziesiąte są nieparzyste = zaokrąglić w górę - jedno miejsce i dziesiąte miejsce są mieszane = zaokrąglone w dół * Zero nie jest nieparzyste * Odwrócone dla liczb ujemnych
Arkham Angel
@ArkhamAngel, to wydaje się trudniejsze do zapamiętania niż po prostu „zrób nawet ostatnią cyfrę” :-)
Liczba całkowita najbliższa a. Jeśli ułamkowa część a znajduje się w połowie drogi między dwiema liczbami całkowitymi, z których jedna jest parzysta, a druga nieparzysta, zwracana jest liczba parzysta.
... i tak 2,5, będące w połowie między 2 a 3, jest zaokrąglane w dół do liczby parzystej (2). nazywa się to zaokrąglaniem za pomocą Bankera (lub zaokrąglaniem do parzystości) i jest powszechnie stosowanym standardem zaokrąglania.
Ten sam artykuł MSDN:
Zachowanie tej metody jest zgodne z normą IEEE 754, sekcja 4. Ten rodzaj zaokrąglania jest czasami nazywany zaokrąglaniem do najbliższego lub zaokrąglania bankierskiego. Minimalizuje błędy zaokrąglania wynikające z konsekwentnego zaokrąglania wartości punktu środkowego w jednym kierunku.
Możesz określić inne zachowanie zaokrąglania, wywołując przeciążenia Math.Round, które przyjmują MidpointRoundingtryb.
Zachowanie tej metody jest zgodne z normą IEEE 754, sekcja 4. Ten rodzaj zaokrąglania jest czasami nazywany zaokrąglaniem do najbliższego lub zaokrąglania bankierskiego.
Możesz określić zachowanie Math.Roundprzy użyciu przeciążenia:
Rozważ zadanie zaokrąglenia liczby zawierającej ułamek do, powiedzmy, liczby całkowitej. Proces zaokrąglania w takich okolicznościach polega na określeniu, która liczba całkowita najlepiej odpowiada zaokrąglanej liczbie.
W przypadku zaokrąglania wspólnego lub „arytmetycznego” jasne jest, że 2.1, 2.2, 2.3 i 2.4 zaokrąglają do 2,0; oraz 2.6, 2.7, 2.8 i 2.9 do 3.0.
Pozostawia to 2.5, co nie jest bliższe 2,0 niż 3,0. Od Ciebie zależy, czy wybierzesz między 2,0 a 3,0, oba będą równie ważne.
Dla liczb ujemnych -2,1, -2,2, -2,3 i -2,4 staną się na -2,0; a -2,6, 2,7, 2,8 i 2,9 staną się -3,0 w zaokrągleniu arytmetycznym.
Dla -2,5 potrzebny jest wybór między -2,0 a -3,0.
Inne formy zaokrąglania
„Zaokrąglanie w górę” przyjmuje dowolną liczbę z miejscami dziesiętnymi i czyni ją kolejną „liczbą całkowitą”. Zatem nie tylko rundy 2.5 i 2.6 do 3.0, ale także 2.1 i 2.2.
Zaokrąglanie w górę przesuwa liczby dodatnie i ujemne od zera. Na przykład. 2,5 do 3,0 i -2,5 do -3,0.
„Zaokrąglanie w dół” obcina liczby, odcinając niechciane cyfry. To powoduje przesuwanie liczb w kierunku zera. Na przykład. 2,5 do 2,0 i -2,5 do -2,0
W „zaokrąglaniu bankiera” - w swojej najczęstszej postaci - zaokrąglane .5 jest zaokrąglane w górę lub w dół, aby wynik zaokrąglania był zawsze liczbą parzystą. Tak więc 2,5 zaokrągla do 2,0, 3,5 do 4,0, 4,5 do 4,0, 5,5 do 6,0 i tak dalej.
„Alternatywne zaokrąglanie” naprzemiennie wykonuje proces dla dowolnego .5 pomiędzy zaokrąglaniem w dół i zaokrąglaniem w górę.
„Losowe zaokrąglanie” zaokrągla a .5 w górę lub w dół całkowicie losowo.
Symetria i asymetria
Mówi się, że funkcja zaokrąglania jest „symetryczna”, jeśli albo zaokrągla wszystkie liczby od zera, albo zaokrągla wszystkie liczby w kierunku zera.
Funkcja jest „asymetryczna”, jeśli zaokrągla liczby dodatnie w kierunku zera, a liczby ujemne od zera. Np. Od 2,5 do 2,0; i -2,5 do -3,0.
Również asymetryczna jest funkcja, która zaokrągla liczby dodatnie od zera i liczby ujemne w kierunku zera. Na przykład. Od 2,5 do 3,0; i -2,5 do -2,0.
Przez większość czasu ludzie myślą o zaokrąglaniu symetrycznym, w którym -2,5 będzie zaokrąglane w kierunku -3,0, a 3,5 będzie zaokrąglane w kierunku 4,0. (w C #Round(AwayFromZero))
Domyślne MidpointRounding.ToEvenlub zaokrąglanie przez Bankierów ( 2,5 staje się 2, 4,5 staje się 4 itd. ) Uprzedziło mnie wcześniej pisaniem raportów do księgowości, więc napiszę kilka słów o tym, czego się dowiedziałem wcześniej i patrząc na to ten post.
Kim są ci bankierzy, którzy zaokrąglają liczby parzyste (być może brytyjscy bankierzy!)?
Z wikipedii
Geneza terminu zaokrąglania przez bankierów jest bardziej niejasna. Jeśli ta metoda zaokrąglania była kiedykolwiek standardem w bankowości, dowody okazały się niezwykle trudne do znalezienia. Przeciwnie, sekcja 2 raportu Komisji Europejskiej Wprowadzenie euro i zaokrąglanie kwot walutowych sugeruje, że wcześniej nie było standardowego podejścia do zaokrąglania w bankowości; i określa, że kwoty „w połowie drogi” należy zaokrąglić w górę.
Wydaje się to bardzo dziwnym sposobem zaokrąglania, szczególnie w przypadku bankowości, chyba że banki używają do przyjmowania dużej liczby depozytów o równych kwotach. Wpłać 2,4 miliona funtów, ale nazwiemy to 2 miliony funtów.
Standard IEEE 754 pochodzi z 1985 roku i oferuje oba sposoby zaokrąglania, ale bankier jest zalecany przez standard. W tym artykule na Wikipedii znajduje się długa lista sposobów zaokrąglania języków (popraw mnie, jeśli któreś z poniższych stwierdzeń jest błędne) i większość z nich nie używa bankierów, ale zaokrąglania, którego uczysz w szkole:
C / C ++ round () z matematyki. H zaokrągla od zera (nie zaokrąglanie przez bankiera)
Java Math.Round zaokrągla wartość od zera (wyrównuje wynik, dodaje 0,5, rzutuje na liczbę całkowitą). W BigDecimal istnieje alternatywa
Dzięki za informację. Nigdy nie zdawałem sobie z tego sprawy. Twój przykład o milionach wyśmiewa to trochę, ale nawet jeśli zaokrąglisz centy, konieczność zapłaty odsetek na 10 milionach rachunków bankowych będzie kosztować bank dużo, jeśli wszystkie pół centy zostaną zaokrąglone w górę, lub będzie kosztować klientów, jeśli wszyscy pół centa są zaokrąglane w dół. Mogę sobie wyobrazić, że jest to uzgodniony standard. Nie jestem jednak pewien, czy bankierzy tak naprawdę go używają. Większość klientów nie zauważy zaokrąglania w dół, przynosząc przy tym dużo pieniędzy, ale mogę sobie wyobrazić, że jest to wymagane przez prawo, jeśli mieszkasz w kraju, w którym obowiązują przepisy przyjazne dla klientów
Harald Coppoolse
15
Z MSDN:
Domyślnie Math.Round używa MidpointRounding.ToEven. Większość ludzi nie jest zaznajomiona z „zaokrąglaniem do parzystości” jako alternatywą, „zaokrąglania od zera” częściej uczy się w szkole. .NET domyślnie przyjmuje wartość „Zaokrąglanie do parzystej”, ponieważ jest statystycznie lepszy, ponieważ nie dzieli tendencji do „zaokrąglania od zera” do zaokrąglania w górę nieco częściej niż zaokrągla w dół (zakładając, że zaokrąglane liczby są dodatnie. )
Liczba najbliższa wartości z dokładnością równą cyfrom. Jeśli wartość znajduje się w połowie odległości między dwiema liczbami, z których jedna jest parzysta, a druga nieparzysta, wówczas zwracana jest liczba parzysta. Jeśli dokładność wartości jest mniejsza niż cyfry, wówczas wartość jest zwracana bez zmian.
Zachowanie tej metody jest zgodne z normą IEEE 754, sekcja 4. Ten rodzaj zaokrąglania jest czasami nazywany zaokrąglaniem do najbliższego lub zaokrąglania bankierskiego. Jeśli cyfry wynoszą zero, ten rodzaj zaokrąglania jest czasami nazywany zaokrąglaniem w kierunku zera.
Silverlight nie obsługuje opcji MidpointRounding. Oto metoda rozszerzenia dla Silverlight, która dodaje wyliczenie MidpointRounding:
publicenumMidpointRounding{ToEven,AwayFromZero}publicstaticclassDecimalExtensions{publicstaticdecimalRound(thisdecimal d,MidpointRounding mode){return d.Round(0, mode);}/// <summary>/// Rounds using arithmetic (5 rounds up) symmetrical (up is away from zero) rounding/// </summary>/// <param name="d">A Decimal number to be rounded.</param>/// <param name="decimals">The number of significant fractional digits (precision) in the return value.</param>/// <returns>The number nearest d with precision equal to decimals. If d is halfway between two numbers, then the nearest whole number away from zero is returned.</returns>publicstaticdecimalRound(thisdecimal d,int decimals,MidpointRounding mode){if( mode ==MidpointRounding.ToEven){returndecimal.Round(d, decimals);}else{decimal factor =Convert.ToDecimal(Math.Pow(10, decimals));int sign =Math.Sign(d);returnDecimal.Truncate(d * factor +0.5m* sign)/ factor;}}}
>.5daje takie samo zachowanie jak Math.Round. Pytanie brzmi, co się dzieje, gdy dokładnie jest część dziesiętna 0.5. Math.Round pozwala określić żądany algorytm zaokrąglania
Panagiotis Kanavos
-2
Jest to brzydkie jak całe piekło, ale zawsze powoduje prawidłowe zaokrąglanie arytmetyczne.
Próba z 1,905 z 2 miejscami po przecinku da 1,91 zgodnie z oczekiwaniami, ale Math.Round(1.905,2,MidpointRounding.AwayFromZero)daje 1,90! Metoda Math.Round jest absolutnie niespójna i nie nadaje się do większości podstawowych problemów, które mogą napotkać programiści. Muszę sprawdzić, czy (int) 1.905 * decimalPowerOfTen = Math.Round(number * decimalPowerOfTen, 2)nie chcę zaokrąglać w górę tego, co powinno być zaokrąglane w dół.
Math.Round(2.5, 0, MidpointRounding.AwayFromZero);
1.005
nie może być dokładnie reprezentowany podwójnie. To pewnie1.00499...
. Jeśli użyjeszDecimal
tego problemu, zniknie. Istnienie przeciążenia Math.Round, które wymaga podwójnej liczby cyfr dziesiętnych, jest wątpliwym wyborem IMO, ponieważ rzadko działa w znaczący sposób.Odpowiedzi:
Po pierwsze, i tak nie byłby to błąd C # - byłby to błąd .NET. C # to język - nie decyduje o sposobie
Math.Round
implementacji.Po drugie, nie - jeśli przeczytasz dokumenty , zobaczysz, że domyślne zaokrąglenie to „zaokrąglenie do parzystego” (zaokrąglenie bankiera):
Możesz określić, jak
Math.Round
zaokrąglić punkty środkowe, używając przeciążenia, które przyjmujeMidpointRounding
wartość. Jest jedno przeciążenieMidpointRounding
odpowiadające każdemu z przeciążeń, które go nie ma:Round(Decimal)
/Round(Decimal, MidpointRounding)
Round(Double)
/Round(Double, MidpointRounding)
Round(Decimal, Int32)
/Round(Decimal, Int32, MidpointRounding)
Round(Double, Int32)
/Round(Double, Int32, MidpointRounding)
To, czy to ustawienie domyślne zostało dobrze wybrane, czy nie, to inna sprawa. (
MidpointRounding
został wprowadzony tylko w .NET 2.0. Do tego czasu nie jestem pewien, czy istniał jakiś łatwy sposób na wdrożenie pożądanego zachowania bez robienia tego sam.) W szczególności historia pokazała, że nie jest to oczekiwane zachowanie - i w większości przypadków jest to grzech główny w projekcie API. Rozumiem, dlaczego zaokrąglanie za pomocą bankiera jest przydatne ... ale dla wielu wciąż jest zaskoczeniem.Być może zainteresuje Cię najbliższa enum Java (enum
RoundingMode
), która oferuje jeszcze więcej opcji. (Nie dotyczy to tylko punktów środkowych).źródło
Nazywa się to zaokrąglaniem do parzystego (lub zaokrąglania bankowego), co jest prawidłową strategią zaokrąglania w celu minimalizacji narastających błędów sum
(MidpointRounding.ToEven)
. Teoria jest taka, że jeśli zawsze zaokrąglasz liczbę 0,5 w tym samym kierunku, błędy będą narastały szybciej (zaokrąglanie do parzystej ma to zminimalizować) (a) .Skorzystaj z tych linków, aby uzyskać opisy MSDN:
Math.Floor
, który zaokrągla w dół w kierunku ujemnej nieskończoności.Math.Ceiling
, który zaokrągla w górę w kierunku dodatniej nieskończoności.Math.Truncate
, który zaokrągla w górę lub w dół w kierunku zera.Math.Round
, który zaokrągla do najbliższej liczby całkowitej lub określonej liczby miejsc dziesiętnych. Możesz określić zachowanie, jeśli jest dokładnie w jednakowej odległości między dwiema możliwościami, takimi jak zaokrąglanie, tak aby ostatnia cyfra była parzysta („Round(2.5,MidpointRounding.ToEven)
” staje się 2) lub tak, że jest dalej od zera („Round(2.5,MidpointRounding.AwayFromZero)
” staje się 3).Poniższy schemat i tabela mogą pomóc:
Zauważ, że
Round
jest o wiele potężniejszy niż się wydaje, po prostu dlatego, że może zaokrąglać do określonej liczby miejsc po przecinku. Wszystkie pozostałe zawsze zaokrąglają do dziesiętnych. Na przykład:W przypadku innych funkcji musisz użyć funkcji zwielokrotniania / dzielenia, aby osiągnąć ten sam efekt:
(a) Oczywiście, teoria ta zależy od tego, że twoje dane mają dość równomierny rozkład wartości na parzyste połowy (0,5, 2,5, 4,5, ...) i nieparzyste połowy (1,5, 3,5, ...).
Jeśli wszystkie „pół-wartości” są równe (na przykład), błędy będą kumulować się tak szybko, jakbyś zawsze zaokrąglał w górę.
źródło
e
tykać (= 2.8) nie powinno być dalej, niż2
tyka?Z MSDN zwraca Math.Round (double a) :
... i tak 2,5, będące w połowie między 2 a 3, jest zaokrąglane w dół do liczby parzystej (2). nazywa się to zaokrąglaniem za pomocą Bankera (lub zaokrąglaniem do parzystości) i jest powszechnie stosowanym standardem zaokrąglania.
Ten sam artykuł MSDN:
Możesz określić inne zachowanie zaokrąglania, wywołując przeciążenia Math.Round, które przyjmują
MidpointRounding
tryb.źródło
Powinieneś sprawdzić MSDN pod kątem
Math.Round
:Możesz określić zachowanie
Math.Round
przy użyciu przeciążenia:źródło
Charakter zaokrąglania
Rozważ zadanie zaokrąglenia liczby zawierającej ułamek do, powiedzmy, liczby całkowitej. Proces zaokrąglania w takich okolicznościach polega na określeniu, która liczba całkowita najlepiej odpowiada zaokrąglanej liczbie.
W przypadku zaokrąglania wspólnego lub „arytmetycznego” jasne jest, że 2.1, 2.2, 2.3 i 2.4 zaokrąglają do 2,0; oraz 2.6, 2.7, 2.8 i 2.9 do 3.0.
Pozostawia to 2.5, co nie jest bliższe 2,0 niż 3,0. Od Ciebie zależy, czy wybierzesz między 2,0 a 3,0, oba będą równie ważne.
Dla liczb ujemnych -2,1, -2,2, -2,3 i -2,4 staną się na -2,0; a -2,6, 2,7, 2,8 i 2,9 staną się -3,0 w zaokrągleniu arytmetycznym.
Dla -2,5 potrzebny jest wybór między -2,0 a -3,0.
Inne formy zaokrąglania
„Zaokrąglanie w górę” przyjmuje dowolną liczbę z miejscami dziesiętnymi i czyni ją kolejną „liczbą całkowitą”. Zatem nie tylko rundy 2.5 i 2.6 do 3.0, ale także 2.1 i 2.2.
Zaokrąglanie w górę przesuwa liczby dodatnie i ujemne od zera. Na przykład. 2,5 do 3,0 i -2,5 do -3,0.
„Zaokrąglanie w dół” obcina liczby, odcinając niechciane cyfry. To powoduje przesuwanie liczb w kierunku zera. Na przykład. 2,5 do 2,0 i -2,5 do -2,0
W „zaokrąglaniu bankiera” - w swojej najczęstszej postaci - zaokrąglane .5 jest zaokrąglane w górę lub w dół, aby wynik zaokrąglania był zawsze liczbą parzystą. Tak więc 2,5 zaokrągla do 2,0, 3,5 do 4,0, 4,5 do 4,0, 5,5 do 6,0 i tak dalej.
„Alternatywne zaokrąglanie” naprzemiennie wykonuje proces dla dowolnego .5 pomiędzy zaokrąglaniem w dół i zaokrąglaniem w górę.
„Losowe zaokrąglanie” zaokrągla a .5 w górę lub w dół całkowicie losowo.
Symetria i asymetria
Mówi się, że funkcja zaokrąglania jest „symetryczna”, jeśli albo zaokrągla wszystkie liczby od zera, albo zaokrągla wszystkie liczby w kierunku zera.
Funkcja jest „asymetryczna”, jeśli zaokrągla liczby dodatnie w kierunku zera, a liczby ujemne od zera. Np. Od 2,5 do 2,0; i -2,5 do -3,0.
Również asymetryczna jest funkcja, która zaokrągla liczby dodatnie od zera i liczby ujemne w kierunku zera. Na przykład. Od 2,5 do 3,0; i -2,5 do -2,0.
Przez większość czasu ludzie myślą o zaokrąglaniu symetrycznym, w którym -2,5 będzie zaokrąglane w kierunku -3,0, a 3,5 będzie zaokrąglane w kierunku 4,0. (w C #
Round(AwayFromZero)
)źródło
Domyślne
MidpointRounding.ToEven
lub zaokrąglanie przez Bankierów ( 2,5 staje się 2, 4,5 staje się 4 itd. ) Uprzedziło mnie wcześniej pisaniem raportów do księgowości, więc napiszę kilka słów o tym, czego się dowiedziałem wcześniej i patrząc na to ten post.Kim są ci bankierzy, którzy zaokrąglają liczby parzyste (być może brytyjscy bankierzy!)?
Z wikipedii
Wydaje się to bardzo dziwnym sposobem zaokrąglania, szczególnie w przypadku bankowości, chyba że banki używają do przyjmowania dużej liczby depozytów o równych kwotach. Wpłać 2,4 miliona funtów, ale nazwiemy to 2 miliony funtów.
Standard IEEE 754 pochodzi z 1985 roku i oferuje oba sposoby zaokrąglania, ale bankier jest zalecany przez standard. W tym artykule na Wikipedii znajduje się długa lista sposobów zaokrąglania języków (popraw mnie, jeśli któreś z poniższych stwierdzeń jest błędne) i większość z nich nie używa bankierów, ale zaokrąglania, którego uczysz w szkole:
źródło
Z MSDN:
http://msdn.microsoft.com/en-us/library/system.math.round.aspx
źródło
Ponieważ Silverlight nie obsługuje opcji MidpointRounding, musisz napisać własną. Coś jak:
Aby zapoznać się z przykładami użycia tego rozszerzenia jako rozszerzenia, zobacz post: .NET i Silverlight Rounding
źródło
Miałem ten problem, gdy mój serwer SQL zaokrągla w górę 0,5 do 1, podczas gdy moja aplikacja C # nie. Widzisz dwa różne wyniki.
Oto implementacja z int / long. W ten sposób Java się kręci.
Jest to prawdopodobnie najbardziej wydajna metoda, o której możesz pomyśleć.
Jeśli chcesz zachować podwójność i używać precyzji dziesiętnej, to tak naprawdę wystarczy użyć wykładników 10 na podstawie liczby miejsc dziesiętnych.
Możesz wprowadzić ujemną liczbę dziesiętną dla kropek dziesiętnych, a także słowo w porządku.
źródło
Prosty sposób to:
źródło
Ten post zawiera odpowiedź, której szukasz:
http://weblogs.asp.net/sfurman/archive/2003/03/07/3537.aspx
Zasadniczo tak mówi:
Zwracana wartość
Liczba najbliższa wartości z dokładnością równą cyfrom. Jeśli wartość znajduje się w połowie odległości między dwiema liczbami, z których jedna jest parzysta, a druga nieparzysta, wówczas zwracana jest liczba parzysta. Jeśli dokładność wartości jest mniejsza niż cyfry, wówczas wartość jest zwracana bez zmian.
Zachowanie tej metody jest zgodne z normą IEEE 754, sekcja 4. Ten rodzaj zaokrąglania jest czasami nazywany zaokrąglaniem do najbliższego lub zaokrąglania bankierskiego. Jeśli cyfry wynoszą zero, ten rodzaj zaokrąglania jest czasami nazywany zaokrąglaniem w kierunku zera.
źródło
Silverlight nie obsługuje opcji MidpointRounding. Oto metoda rozszerzenia dla Silverlight, która dodaje wyliczenie MidpointRounding:
Źródło: http://anderly.com/2009/08/08/silverlight-midpoint-rounding-solution/
źródło
za pomocą niestandardowego zaokrąglenia
źródło
>.5
daje takie samo zachowanie jakMath.Round
. Pytanie brzmi, co się dzieje, gdy dokładnie jest część dziesiętna0.5
. Math.Round pozwala określić żądany algorytm zaokrąglaniaJest to brzydkie jak całe piekło, ale zawsze powoduje prawidłowe zaokrąglanie arytmetyczne.
źródło
Math.Round
i określaniem, w jaki sposób ma on się odbywać.Oto jak musiałem to obejść:
Próba z 1,905 z 2 miejscami po przecinku da 1,91 zgodnie z oczekiwaniami, ale
Math.Round(1.905,2,MidpointRounding.AwayFromZero)
daje 1,90! Metoda Math.Round jest absolutnie niespójna i nie nadaje się do większości podstawowych problemów, które mogą napotkać programiści. Muszę sprawdzić, czy(int) 1.905 * decimalPowerOfTen = Math.Round(number * decimalPowerOfTen, 2)
nie chcę zaokrąglać w górę tego, co powinno być zaokrąglane w dół.źródło
Math.Round(1.905,2,MidpointRounding.AwayFromZero)
powraca1.91