Существует несколько распространенных способов округления до фиксированного числа десятичных знаков в JavaScript. У каждого из них есть определенные проблемы.
Number.protototype.toFixed метод
Number(x).toFixed(digits)
Этот метод создает строку с запрошенным количеством цифр. Однако он округляет числа, оканчивающиеся на 5, неправильно примерно в 9% случаев. 1015 *, но округляется неправильно примерно в 0,7% случаев.
метод сложения и вычитания экспоненты
Math.round( x + 'e' + digits ) + 'e-' + digits;
Это дает число, округленное до digits
, и округляется правильно. Но у него есть фатальный недостаток - для входных значений меньше 1e-6 он возвращает NaN
.
Я написал функцию, которая использует метод сложения и вычитания экспоненты, но позволяет избежать фатальной ошибка для малых входных значений. Доступно на github .
/**
* round number `x` to `digits` number of digits after decimal point
*/
function roundToFixed (val, digits = 0) {
if (typeof val === 'number' && typeof digits === 'number'
&& Number.isInteger(digits) &&
(digits === 0 || Math.sign(digits) === 1)) {
const valF = numToFloat(val);
const valFNew = numToFloat(
Math.round(+(valF.mant + 'e' + (valF.exp + digits)))
);
return +(valFNew.mant + 'e' + (valFNew.exp - digits));
}
return NaN;
}
/**
* convert number to Float object
*/
function numToFloat (val) {
const [mant, exp] = Number(val)
.toExponential()
.split('e')
.map(str => +str);
return {
mant,
exp
};
}