Czy coś mi umyka?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Dlaczego nie.toFixed()
zwróci ciąg?
Chcę zaokrąglić liczbę do 2 cyfr dziesiętnych.
Czy coś mi umyka?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Dlaczego nie.toFixed()
zwróci ciąg?
Chcę zaokrąglić liczbę do 2 cyfr dziesiętnych.
Odpowiedzi:
Zwraca łańcuch, ponieważ 0.1 i jego moce (które są używane do wyświetlania ułamków dziesiętnych) nie są reprezentowalne (przynajmniej nie z pełną dokładnością) w binarnych systemach zmiennoprzecinkowych.
Na przykład 0,1 to naprawdę 0,1000000000000000055511151231257827021181583404541015625, a 0,01 to naprawdę 0,01000000000000000020816681711721685132943093776702880859375. (Dzięki BigDecimal
za udowodnienie mojej racji. :-P)
Dlatego (w przypadku braku dziesiętnego typu zmiennoprzecinkowego lub wymiernego), wyprowadzenie go jako łańcucha jest jedynym sposobem, aby uzyskać dokładną precyzję wymaganą do wyświetlenia.
toFixed
to funkcja formatująca, której jedynym celem jest konwersja liczby na ciąg znaków, formatowanie jej przy użyciu określonej liczby miejsc po przecinku. Powodem, dla którego zwraca ciąg, jest to, że powinien zwrócić ciąg, a gdyby toStringFixed
zamiast tego został nazwany , OP nie byłby zaskoczony wynikami. Jedynym problemem jest to, że OP spodziewał się, że będzie działać tak Math.round
, jak bez konsultacji z referencjami JS.
Number.prototype.toFixed
to funkcja przeznaczona do formatowania liczby przed jej wydrukowaniem. To z rodziny toString
, toExponential
i toPrecision
.
Aby zaokrąglić liczbę, wykonaj następujące czynności:
someNumber = 42.008;
someNumber = Math.round( someNumber * 1e2 ) / 1e2;
someNumber === 42.01;
// if you need 3 digits, replace 1e2 with 1e3 etc.
// or just copypaste this function to your code:
function toFixedNumber(num, digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(num*pow) / pow;
}
.
Jeśli potrzebujesz funkcji „ natywnej ”, możesz rozszerzyć prototyp:
Number.prototype.toFixedNumber = function(digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(this*pow) / pow;
}
someNumber = 42.008;
someNumber = someNumber.toFixedNumber(2);
someNumber === 42.01;
//or even hexadecimal
someNumber = 0xAF309/256 //which is af3.09
someNumber = someNumber.toFixedNumber(1, 16);
someNumber.toString(16) === "af3.1";
Należy jednak pamiętać, że zanieczyszczenie prototypu jest uważane za złe podczas pisania modułu, ponieważ moduły nie powinny mieć żadnych skutków ubocznych. Tak więc w przypadku modułu użyj pierwszej funkcji .
type Number
. Rzecz w tym, że +(anyValue)
zawsze zwraca liczbę - np. +("45")
zwraca 45
, +(new Number(42))
zwraca 42
. To trochę jak silne wpisywanie funkcji. Jeśli
someNumber = Math.round( 42.008 * 1e2 ) / 1e2;
nie jest 42.01
, to jest ~42.0099999999999980
. Przyczyna: numer 42.01
nie istnieje i jest zaokrąglany do najbliższej istniejącej liczby. btw, sprawdź numery, toPrecision(18)
aby wydrukować je ze wszystkimi odpowiednimi cyframi.
Rozwiązałem ten problem, zmieniając to:
someNumber = someNumber.toFixed(2)
...do tego:
someNumber = +someNumber.toFixed(2);
Jednak spowoduje to przekonwertowanie liczby na ciąg i ponownie ją przeanalizuje, co będzie miało znaczący wpływ na wydajność. Jeśli zależy Ci na wydajności lub bezpieczeństwie typu, sprawdź również pozostałe odpowiedzi.
someNumber = Math.round(someNumber * 1e2) / 1e2
! Zobacz moją odpowiedź w bardziej ogólny sposób.
Dlaczego nie używać parseFloat
?
var someNumber = 123.456;
someNumber = parseFloat(someNumber.toFixed(2));
alert(typeof(someNumber));
//alerts number
Oczywiście zwraca ciąg. Jeśli chcesz zaokrąglić zmienną numeryczną, użyjesz zamiast tego Math.round (). Punkt toFixed służy do formatowania liczby ze stałą liczbą miejsc dziesiętnych do wyświetlenia użytkownikowi .
Czego spodziewałbyś się, że zwróci, gdy ma sformatować liczbę? Jeśli masz liczbę, nie możesz prawie nic z nią zrobić, ponieważ np. 2 == 2.0 == 2.00
Itd., Więc musi to być ciąg.
Aby podać przykład, dlaczego musi to być ciąg:
Jeśli sformatujesz 1. naFixed (2), otrzymasz „1,00”.
To nie to samo, co 1, ponieważ 1 nie ma 2 miejsc po przecinku.
Wiem, że JavaScript nie jest dokładnie językiem wydajnościowym , ale jest szansa, że uzyskasz lepszą wydajność zaokrąglania, jeśli użyjesz czegoś takiego: roundedValue = Math.round (value * 100) * 0,01
Ponieważ jego głównym zastosowaniem jest wyświetlanie liczb? Jeśli chcesz zaokrąglić liczby, użyj Math.round()
odpowiednich współczynników.
'42'
jest to liczba ... a to nie jest. Tylko dlatego, że ciąg zawiera tylko cyfry, nie czyni go liczbą. To nie jest PHP. :-P
Oto nieco bardziej funkcjonalna wersja m93a
udzielonej odpowiedzi .
const toFixedNumber = (toFixTo = 2, base = 10) => num => {
const pow = Math.pow(base, toFixTo)
return +(Math.round(num * pow) / pow)
}
const oneNumber = 10.12323223
const result1 = toFixedNumber(2)(oneNumber) // 10.12
const result2 = toFixedNumber(3)(oneNumber) // 10.123
// or using pipeline-operator
const result3 = oneNumber |> toFixedNumber(2) // 10.12