Я что-то здесь упускаю?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Почему же.toFixed()
возвращает строку?
Я хочу округлить число до 2 десятичных цифр.
Я что-то здесь упускаю?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Почему же.toFixed()
возвращает строку?
Я хочу округлить число до 2 десятичных цифр.
Ответы:
Он возвращает строку, потому что 0,1 и ее степени (которые используются для отображения десятичных дробей) не представимы (по крайней мере, не с полной точностью) в двоичных системах с плавающей запятой.
Например, 0,1 действительно 0,1000000000000000055511151231257827021181583404541015625, а 0,01 действительно 0,01000000000000000020816681711721685132943093776702880859375. (Спасибо BigDecimal
за доказательство моей точки. :-P)
Поэтому (при отсутствии десятичного числа с плавающей запятой или типа рациональных чисел) вывод его в виде строки - единственный способ обрезать его с точностью, необходимой для отображения.
toFixed
это функция форматирования, единственная цель которой - преобразовать число в строку и отформатировать его с использованием указанного числа десятичных знаков. Причина, по которой он возвращает строку, состоит в том, что он должен возвращать строку, и если бы она была названа toStringFixed
вместо этого, OP не удивился бы результатам. Единственная проблема здесь в том, что OP ожидал, что он будет работать Math.round
, не обращаясь к JS.
Number.prototype.toFixed
это функция, предназначенная для форматирования числа перед его печатью. Это из семьи toString
, toExponential
и toPrecision
.
Чтобы округлить число, вы должны сделать это:
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;
}
,
Или, если вам нужна « родная » функция, вы можете расширить прототип:
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";
Однако имейте в виду, что загрязнение прототипа считается плохим, когда вы пишете модуль, поскольку модули не должны иметь побочных эффектов. Итак, для модуля используйте первую функцию .
type Number
. Дело в том, что +(anyValue)
всегда возвращает число - например. +("45")
возвращается 45
, +(new Number(42))
возвращается 42
. Это похоже на строгую типизацию функции. Если вы привыкли к этому, вы можете избежать множества ошибок :)
someNumber = Math.round( 42.008 * 1e2 ) / 1e2;
нет 42.01
, это так ~42.0099999999999980
. Причина: число 42.01
не существует и округляется до ближайшего существующего числа. Кстати, пробные номера, toPrecision(18)
чтобы напечатать его со всеми соответствующими цифрами.
Я решил эту проблему, изменив это:
someNumber = someNumber.toFixed(2)
...к этому:
someNumber = +someNumber.toFixed(2);
Однако это преобразует число в строку и анализирует его снова, что окажет значительное влияние на производительность. Если вы заботитесь о производительности или безопасности типов, проверьте и другие ответы.
someNumber = Math.round(someNumber * 1e2) / 1e2
! Смотрите мой ответ для более обобщенного способа.
Почему бы не использовать parseFloat
?
var someNumber = 123.456;
someNumber = parseFloat(someNumber.toFixed(2));
alert(typeof(someNumber));
//alerts number
Конечно, он возвращает строку. Если вы хотите округлить числовую переменную, используйте вместо этого Math.round (). Смысл toFixed состоит в том, чтобы отформатировать число с фиксированным числом десятичных знаков для отображения пользователю .
Что вы ожидаете, что он вернется, когда он должен отформатировать число? Если у вас есть номер, вы не можете ничего с ним сделать, потому что, например, 2 == 2.0 == 2.00
и т. Д., Так что это должна быть строка.
Чтобы привести пример того, почему это должна быть строка:
Если вы отформатируете 1.toFixed (2), вы получите «1,00».
Это не то же самое, что 1, поскольку 1 не имеет 2 десятичных знаков.
Я знаю, что JavaScript не совсем язык производительности , но есть вероятность, что вы получите более высокую производительность для округления, если вы используете что-то вроде: roundedValue = Math.round (value * 100) * 0.01
Потому что его основное использование - отображение чисел? Если вы хотите округлить числа, используйте соответствующие Math.round()
факторы.
'42'
как это число ... что это не так. Тот факт, что строка содержит только цифры, не делает ее числом. Это не PHP. :-P
Вот несколько более функциональный вариант ответа m93a
.
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