Я щось тут пропускаю?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Чому ж.toFixed()
повертає рядок?
Я хочу округлити число до двох десяткових цифр.
Я щось тут пропускаю?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Чому ж.toFixed()
повертає рядок?
Я хочу округлити число до двох десяткових цифр.
Відповіді:
Він повертає рядок, оскільки 0,1 та його повноваження (які використовуються для відображення десяткових дробів) не є представними (принаймні, не з повною точністю) у двійкових системах з плаваючою комою.
Наприклад, 0,1 дійсно 0,1000000000000000055511151231257827021181583404541015625, а 0,01 дійсно 0,01000000000000000020816681711721685132943093776702880859375. (Дякую BigDecimal
за те, що ви довели свою думку. :-P)
Тому (відсутня десяткова плаваюча точка чи раціональний тип числа), виведення його у вигляді рядка - єдиний спосіб налагодити його точно до точності, необхідної для відображення.
toFixed
це функція форматування, яка має єдину мету перетворити число в рядок, відформатувавши його за допомогою вказаної кількості десяткових знаків. Причина, по якій він повертає рядок, полягає в тому, що вона повинна повернути рядок, і якби вона була назначена toStringFixed
замість, ОП не буде здивована результатами. Єдине питання тут полягає в тому, що ОП очікувала, що це буде працювати 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
не існує і округляється до найближчого існуючого числа. btw, перевірити номери, 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 (значення * 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