Matematyka.runda (num) vs num.tofixed (0) i niespójności przeglądarki
Rozważ następujący kod:
for (var i=0;i<3;i++){
var num = i + 0.50;
var output = num + " " + Math.round(num) + " " + num.toFixed(0);
alert(output);
}
W Operze 9.63 dostaję:
0.5 1 0
1.5 2 2
2.5 3 2
W FF 3.03 dostaję:
0.5 1 1
1.5 2 2
2.5 3 3
W IE 7 dostaję:
0.5 1 0
1.5 2 2
2.5 3 3
Zwróć uwagę na pogrubione wyniki. Dlaczego są to niespójności prezent? Czy to oznacza, że toFixed(0)
Należy unikać? Jaki jest prawidłowy sposób zaokrąglania liczby do najbliższej liczby całkowitej?
6 answers
Edit: aby odpowiedzieć na swoją edycję, użyj Math.round
. Możesz również prototypować obiekt Number
tak, aby spełniał Twoje polecenia, jeśli wolisz taką składnię.
Number.prototype.round = function() {
return Math.round(this);
}
var num = 3.5;
alert(num.round())
Nigdy wcześniej nie używałem Number.toFixed()
(głównie dlatego, że większość bibliotek JS dostarcza toInt()
metoda), ale sądząc po twoich wynikach powiedziałbym, że bardziej spójne byłoby stosowanie metod Math
(round
, floor
, ceil
) Następnie toFixed
jeśli spójność między przeglądarkami jest tym, czego szukasz.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-19 18:57:34
FF robi dobrze z toFixed, ponieważ krok 10 poniżej mówi "Jeśli są dwa takie n, wybierz większe n".]}
I jako Grant Wagner powiedział: użyj matematyki.ceil (x) lub Matematyka.floor(x) zamiast x.tofixed () .
Wszystko poniżej pochodzi ze specyfikacji języka ECMAScript :
15.7.4.5
Number.prototype.toFixed (fractionDigits)
Zwraca łańcuch zawierający liczbę reprezentowaną w punkcie stałym notacja z
fractionDigits
cyfry po przecinku. JeślifractionDigits
jest niezdefiniowana,0
zakłada się. W szczególności wykonaj następujące kroki:
- niech
f
będzieToInteger(fractionDigits)
. (IffractionDigits
is undefined, ten krok daje wartość0
).- If
f < 0
orf > 20
, throw aRangeError
exception.- niech
x
będzie tą wartością liczbową.- jeśli
x
jestNaN
, zwraca łańcuch"NaN"
.- niech
s
będzie ciągiem pustym.- jeśli
x ≥ 0
, przejdź do kroku 9.- niech będzie
"-"
.- niech
x = –x
.- jeśli
x ≥ 10^21
, pozwólm = ToString(x)
i przejdź do kroku 20.- niech
n
będzie liczbą całkowitą, dla której dokładna wartość matematycznan ÷ 10^f – x
jest jak najbliżej zera. Jeśli są dwa takien
, wybierz większen
.- Jeśli
n = 0
, niechm
będzie ciągiem"0"
. W przeciwnym razie niechm
będzie łańcuch składający się z cyfr reprezentacji dziesiętnej zn
(w kolejności, bez zer wiodących).- jeśli
f = 0
, przejdź do kroku 20.- niech
k
będzie liczbą znaków wm
.- jeśli
k > f
, przejdź do kroku 18.- niech
z
będzie ciągiem składającym się zf+1–k
wystąpień znak'0'
.- niech
m
będzie konkatenacją łańcuchówz
im
.- niech
k = f + 1
.- niech
a
będzie pierwszymk–f
znakiemm
, ab
będzie pozostałef
znakim
.- niech
m
będzie konkatenacja trzech struna
,"."
, ib
.- zwraca konkatenację łańcuchów
s
im
.Właściwością
length
metodytoFixed
jest1
.Jeśli metoda
toFixed
jest wywołana z więcej niż jednym argumentem, to zachowanie jest nieokreślone (patrz punkt 15).Implementacja może rozszerzyć zachowanie
toFixed
dla wartościfractionDigits
mniejsze niż0
lub większe niż20
. W tym przypadkutoFixed
niekoniecznie rzuciRangeError
dla takich wartości.Uwaga wyjście
toFixed
może być bardziej precyzyjne niżtoString
dla niektóre wartości, ponieważtoString
wyświetla tylko wystarczająco znaczące cyfry aby odróżnić liczbę od sąsiednich wartości liczbowych. Na przykład,(1000000000000000128).toString()
zwraca"1000000000000000100"
, podczas gdy(1000000000000000128).toFixed(0)
zwraca"1000000000000000128"
.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:03:05
Aby rozwiązać swoje dwa oryginalne problemy / pytania:
Matematyka.runda (num) vs num.toFixed (0)
Problem tkwi w błędnym przekonaniu, że powinny one zawsze dawać ten sam rezultat. W rzeczywistości rządzą nimi różne zasady. Spójrz na liczby ujemne, na przykład. Ponieważ Math.round
używa "round half up" jako zasady, zobaczysz, że Math.round(-1.5)
ewaluuje do -1
, mimo że Math.round(1.5)
ewaluuje do 2
.
Number.prototype.toFixed
, z drugiej strony, używa co jest zasadniczo równoważne "zaokrąglenie połowy od zera" zgodnie z zasadą, zgodnie z Krok 6 spec , która zasadniczo mówi, aby traktować negatywy jako liczby dodatnie, a następnie dodać znak ujemny na końcu. Tak więc, (-1.5).toFixed(0) === "-2"
i (1.5).toFixed(0) === "2"
są prawdziwymi wyrażeniami we wszystkich przeglądarkach zgodnych ze specyfikacją. Zauważ, że te wartości są ciągami znaków, a nie liczbami. Zauważ ponadto, że zarówno -1.5.toFixed(0)
, jak i -(1.5).toFixed(0)
są === -2
(liczbą) ze względu na pierwszeństwo operatora.
Przeglądarka niespójności
Większość nowoczesnych przeglądarek-lub przynajmniej te, których można się spodziewać w momencie pisania tego tekstu z wyjątkiem IE-wszyscy powinni poprawnie wdrożyć specyfikacje. (Zgodnie z komentarz Renee , toFixed
problem, który wskazałeś w Operze został naprawiony, prawdopodobnie od czasu, gdy zaczęli używać tego samego silnika JS co Chrome.) Nadal warto to powtórzyć, nawet jeśli specyfikacje były konsekwentnie wdrażane we wszystkich przeglądarkach, zachowanie zdefiniowane w specyfikacji, szczególnie dla toFixed
zaokrąglania, może być nadal nieco nieintuitywne dla" zwykłych śmiertelników "programistów JS, którzy oczekują prawdziwej matematycznej dokładności-zobacz Javascript Tofixed Not Rounding i ten" działa zgodnie z przeznaczeniem " błąd, który został złożony na silniku JS V8 dla przykładów.
Podsumowanie
W skrócie, są to dwie różne funkcje z dwoma różnymi typami zwrotów i dwoma różnymi zestawami reguł zaokrąglania.
Jak inni sugerowane, chciałbym również powiedzieć "użyj dowolnej funkcji pasuje do konkretnego przypadku użycia" (zwracając szczególną uwagę na specyfikę toFixed
, zwłaszcza błędnej implementacji IE). osobiście skłaniałbym się bardziej ku zaleceniu jakiejś wyraźnej kombinacji Edit: ...chociaż po powrocie i przeczytaniu twojego wyjaśnienia, Twój przypadek użycia (zaokrąglenie do liczby całkowitej) zdecydowanie wymaga trafnie nazwanego Math.round/ceil/floor
, ponownie, jak inni wspominali.Math.round
funkcja.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-02-21 15:27:42
Tofixed () Zwraca wartość łańcuchową. Z Języka Javascript: Definitywny Przewodnik
Zamienia liczbę na łańcuch zawierający określoną liczbę cyfry po miejscu dziesiętnym.
Matematyka.round () Zwraca liczbę całkowitą.
Najwyraźniej, toFixed () wydają się być bardziej przydatne dla pieniędzy, na przykład,
'$' + 12.34253.toFixed(2) = '$12.34'
Wielka szkoda, że toFixed () nie wydaje się zaokrąglać jak należy!
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2012-01-24 04:09:59
Zamiast toFixed(0)
użyj Math.ceil()
lub Math.floor()
, w zależności od tego, co jest wymagane.
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2009-02-19 18:44:40
To na pewno tak wygląda, jeśli otrzymujesz niespójne odpowiedzi.
Mogę się tylko domyślać, że twoim celem za pomocą tofixed(0) jest przekształcenie liczby dziesiętnej w liczbę całkowitą, w tym momencie polecam Math.piętro (). Jest trochę więcej dyskusji na temat najlepszego sposobu, aby to zrobić w to pytanie .
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:10:08