Dlaczego Math.Round() zaokrągla połówki w dół?

0

Cześć, uczę się programować w C#
Jestem nauczycielem i aktualnie tworze programik w konsoli do przeliczania punktów na oceny
i frapuje mnie kwestia zaokrąglania za pomocą Math.Round(). Dajmy na to, mamy poniższy kod

double p = 62.5;
Console.WriteLine(Math.Round(p));

Dlaczego wynikiem będzie wypisanie w konsoli liczby 62, a nie poprawnego zaokrąglenia do 63?
Tak, wiem, że aby uporać się z problemem wystarczy napisać

double p = 62.5;
Console.WriteLine(Math.Round(p, MidpointRounding.AwayFromZero));

Interesuje mnie dlaczego zwykłe Math.Round nie działa w takim wypadku?
Wybaczcie, jeśli pytanie jest trywialne, ale gdzie mam zapytać jak nie tu ;)

5

Jest wiele konwencji tego w jaki sposób zaokrąglać połówki.

Zapoznaj się z dokumentacją: https://learn.microsoft.com/en-us/dotnet/api/system.decimal.round#System_Decimal_Round_System_Decimal_

3
ChudyOrzeł napisał(a):

ale gdzie mam zapytać jak nie tu ;)

W dokumentacji (jest bardzo dobra).
Komu jak komu, ale nauczycielowi by wypadało.

1
Riddle napisał(a):

Jest wiele konwencji tego w jaki sposób zaokrąglać połówki.

Zapoznaj się z dokumentacją: https://learn.microsoft.com/en-us/dotnet/api/system.decimal.round#System_Decimal_Round_System_Decimal_

Dziwne i bez sensu to jest. Zamiast trzech ogólnie przyjętych sposobów zaokrągleń (wg cyfry <=4 lub >=5, zawsze w dół, zawsze w górę), są wymyślone różne sposoby zaokrągleń, z których domyślny nie odpowiada ogólnie przyjętej zasadzie 4/5, co zauważył OP i jest w linku na SO.

0

Liczyłem na jakieś proste i szybkie wytłumaczenie ale jeżeli takie nie istnieje, to przekopie się przez dokumentację i wątek na stacku.

5
ChudyOrzeł napisał(a):

Liczyłem na jakieś proste i szybkie wytłumaczenie ale jeżeli takie nie istnieje, to przekopie się przez dokumentację i wątek na stacku.

No zadajesz pytanie które jest już od początku niepoprawne - Dlaczego wynikiem będzie wypisanie w konsoli liczby 62, a nie poprawnego zaokrąglenia do 63? skąd pomysł że tym "poprawnym" zaokrągleniem połówki jest w górę? Wartość .5 jest przecież dokładnie w połowie między dwoma całościami więc nie istnieje ten "bardziej obiektywny sposób", a jedynie umowne konwencje. Niektórzy zaokrąglą je w górę, niektórzy w górę zależnie od potrzeb.

ChudyOrzeł napisał(a):

Liczyłem na jakieś proste i szybkie wytłumaczenie ale jeżeli takie nie istnieje, to przekopie się przez dokumentację i wątek na stacku.

Poza tym to "przekopanie się przez dokumentację" sprowadza się do kliknięcia w link, i przeczytania 5 strategii MidpointRounding: https://learn.microsoft.com/en-us/dotnet/api/system.midpointrounding?view=net-7.0#fields

4

Ale przecież wytłumaczenie jest

The behavior of this method follows IEEE Standard 754, section 4. This kind of rounding is sometimes called round half to even or banker's rounding.

Głębszego wytłumaczenia moim zdaniem nie znajdziesz. Jest jakiś standard, Microsoft uznał, że tak chce mieć domyślnie w .NET i tyle. Sugerując się nazwą banker's rounding można wywnioskować, że taki mają system zaokrąglania kwot. Takie rzeczy nie tyczą się tylko zaokrąglania, ale też formatu dat, czy separatora dziesiętnego.

0
andrzejlisek napisał(a):

Dziwne i bez sensu to jest. Zamiast trzech ogólnie przyjętych sposobów zaokrągleń (wg cyfry <=4 lub >=5, zawsze w dół, zawsze w górę), są wymyślone różne sposoby zaokrągleń, z których domyślny nie odpowiada ogólnie przyjętej zasadzie 4/5, co zauważył OP i jest w linku na SO.

Nigdy nie mów nigdy / zawsze. To "nasze" zaokrąglanie wydaje się europocentryczne.

A z ciekawostek, polscy pracownicy z otoczenia ekonomii dawniej byli uczeni jeszcze innych zaokrągleń, piątka szła w dół lub w górę co drugi raz. W tamtych latach (zaokrąglanie ręczne/kalkulatorem wyrazistych długich kolumn) nawet to miało sens - nie do utrzymania gdy za zaokrąglanie odpowiedzialne jest funkcyjka gdzieś na dole.

2

Bankers rounding używane jest po to żeby statystycznie kwoty zaokrąglały się równomiernie.
Przy stałym zaokrąglaniu 0.5 zawsze w dół albo zawsze w górę któraś że stron byłaby zawsze pokrzywdzona.

1

Nie wiem czy to nie przekłamanie mojej pamięci, ale mi utkwiło że .net zrobili inżynierowie podkupieni z Borlanda :D
(tak na szybko nie znalazłem linka na potwierdzenie)
W Delphi zawsze round działał zgodnie z bankierskim zaokrągleniem.

1
AnyKtokolwiek napisał(a):
andrzejlisek napisał(a):

Dziwne i bez sensu to jest. Zamiast trzech ogólnie przyjętych sposobów zaokrągleń (wg cyfry <=4 lub >=5, zawsze w dół, zawsze w górę), są wymyślone różne sposoby zaokrągleń, z których domyślny nie odpowiada ogólnie przyjętej zasadzie 4/5, co zauważył OP i jest w linku na SO.

Nigdy nie mów nigdy / zawsze. To "nasze" zaokrąglanie wydaje się europocentryczne.

A z ciekawostek, polscy pracownicy z otoczenia ekonomii dawniej byli uczeni jeszcze innych zaokrągleń, piątka szła w dół lub w górę co drugi raz. W tamtych latach (zaokrąglanie ręczne/kalkulatorem wyrazistych długich kolumn) nawet to miało sens - nie do utrzymania gdy za zaokrąglanie odpowiedzialne jest funkcyjka gdzieś na dole.

Możliwe, że problem pojawia się w przypadku, gdy liczba w systemie dziesiętnym wynosi w przybliżeniu na przykład 1,35, a faktycznie wynosi 1,34999999, co wynika z zaokrągleń w reprezentacji zmiennoprzecinkowej. Chcąc zaokrąglić z dokładnością do 0,1 jest dylemat, w którą stronę zaokrąglić. W dół, bo na pozycji setnych stoi cyfra 4, czy w górę, bo ta liczba powinna być traktowana jako 1,35 i taki zapis wypuści ToString()? Jeżeli w reprezentacji binarnej jest faktycznie 1,350000001, to sprawa jest oczywista.

Gdyby zaokrąglanie realizować poprzez pomnożenie przez 10, 100, 1000, zaokrąglenie do całości, a potem podzielenie przez tą liczbę, to może dojdzie do błędu z tego powodu, że pomnożenie i podzielenie liczby zmiennoprzecinkowej przez 10 też może nieznacznie zafałszować wartość?

Nigdzie i nie spotkałem się z zaokrąglaniem na zasadzie, że w przypadku cyfry od 0 do 5 to w dół, a w przypadku cyfry od 6 do 9 to w górę. Może w jakiś bardzo specjalistycznych obszarach tak się robi, ale ogólnie jest przyjęte, że jak jest 5, to w górę. Dopiero teraz się dowiaduję, ze może być jeszcze inaczej.

1 użytkowników online, w tym zalogowanych: 0, gości: 1