Lokalizacyjne dziwactwa – zaokrąglenia

Kontynuując temat „nieświadomej” lokalizacji aplikacji (porzedni wpis), postanowiłem bliżej przyjrzeć się zaokrągleniom liczb zmiennoprzecinkowych. Okazuje się, że i tu może nas spotkać niespodzianka.

W jaki sposób zaokrągla się liczby w C#? Wszystko zależy od potrzeb. Poniżej wybrane sposoby oraz ich rezultaty:

Math.Round(5.1) // 5
Math.Round(5.7) // 6
Math.Round(5.5) // 6
Math.Round(4.5) // 4
Math.Round(4.51) // 5
Math.Floor(4.9) // 4
Math.Ceiling(4.9) // 5
(int)4.9 // 4

Math.Round(4.45, 1) // 4.4
Math.Round(4.55, 1) // 4.6

Rzutowanie nie jest jakimś wyszukanym sposobem, działa jak Math.Floor(). Czyli obcina liczby po przecinku. Co się dzieje natomiast z funkcją Round()? Spójrzmy na otoczenie „całkowite” liczb: 4 < 4.5 < 5 oraz 5 < 5.5 < 6. W takim wypadku wybierana jest najbliższa liczba parzysta (jeżeli po 5 są same zera). Jest to tak zwany bankers’ rounding. Jego zaletą są zbliżone wyniki obliczeń na liczb zaokrąglonych w stosunku do operacji na ich oryginałach.

W Polsce często stosuje się zaokrąglenie w górę począwszy do liczby 5. Jeżeli chcemy uzyskać taki efekt w programie należy skorzystać z przeciążonej metody Round():

Math.Round(4.5, MidpointRounding.AwayFromZero) // 5

Niestety w związku ze sposobem zapisu liczb zmiennoprzecinkowych w systemie binarny, możemy napotkać na różne dziwactwa:

Math.Round(4.145, 2, MidpointRounding.AwayFromZero) // 4.14
Math.Round(4.145, 2) // 4.14
Math.Round(4.125, 2, MidpointRounding.AwayFromZero) // 4.13

Ma to oczywiście związek z błędem numerycznym. Liczbę 0.125 możemy bez problemu zapisać w postaci binarnej w przeciwieństwie do 0.145.

Share

Jedna myśl nt. „Lokalizacyjne dziwactwa – zaokrąglenia

  1. Dlatego w programach, z operacjami na pieniądzach używamy decimali:
    Math.Round((decimal)4.145, 2, MidpointRounding.AwayFromZero)
    4.15
    Math.Round(4.145, 2, MidpointRounding.AwayFromZero)
    4.14

Dodaj komentarz

Twój adres email nie zostanie opublikowany. Pola, których wypełnienie jest wymagane, są oznaczone symbolem *

Spam protection by WP Captcha-Free