2013-03-11 21 views
5

próbuję dostać 2,4/0,8 == 3 PrzejdźGo numer pływak podział

w:=float64(2.4) 
fmt.Println(math.Floor(w/0.8),math.Floor(2.4/0.8)) 

Daje mi "2 3".

Pytanie brzmi, dlaczego math.Floor(w/0.8) nie daje mi 3. Czy jest to dokładny limit liczby zmiennoprzecinkowej?

+0

dobrze, muszę szturchać go dać mi 3, więc robiłam: 'const Posuwanie = 1e-10' i' Math.floor (w/0,8 + nUDGE) ' –

Odpowiedz

9

Wynik programu jest prawidłowy. Reprezentacja wielu liczb rzeczywistych w formacie IEEE nie jest dokładna. Pierwsza liczba to właściwie (w ograniczonej 64-bitowej wersji) mniej niż 3, więc podłoga prawidłowo "2" zwraca. Drugi obliczany jest w czasie kompilacji z większą precyzją.

Zalecane reading.

7

Tak, jest to limit dokładności. float64 jest dość precyzyjny, ale 2.4 nie może być zapisany dokładnie w postaci binarnej. Kiedy obie liczby są stałymi, obliczenia wykonywane są z większą precyzją w czasie kompilacji, a gdy wynik jest zaokrąglany do float64, wychodzi dokładnie do 3. Ale gdy jedna z liczb jest zmienną, obliczenia muszą być wykonane w czasie wykonywania, i wychodzi do 2.9999999999999996, którego poziom przycina się do 2.

0

Mimo że nie odpowiada na pytanie (dlaczego) znalazłem tę stronę, szukając funkcji rundy, więc na wypadek gdyby ktoś uznał ją za pomocną tu jest moje rozwiązanie:

func Round(val float64) (float64) { 
     if float64(int(val)) < val { 
      return float64(int(val) + 1) 
     } 
     return val 
    } 
+1

To nie jest funkcja Round. To nawet nie jest odpowiednia funkcja sufitowa. Użyj biblioteki matematycznej. – JimB

+0

to była poprawna funkcja sufitu dla mojej sprawy. Musiałem zaokrąglić x.x do x + 1, więc oto funkcja. Biblioteka matematyczna nie zapewniała takiej funkcji. Już to sprawdziłem. – hey

+0

Nie należy tego nazywać Round, jeśli jest to funkcja sufitowa. to nie obsługuje negatywów, Inf lub NaN. także [math.Ceil] (http://golang.org/pkg/math/#Ceil). – JimB