вопрос
Однажды служба поддержки клиентов сообщила мне, что поступила жалоба клиента, в которой говорилось, что данные о сумме выставления счета были неверными, а тестовая обратная связь была правильной в браузере IE11.
После расследования было установлено, чтоtoFixed()
вызванный.
причина
посмотриtoFixed()
Разная производительность под хромом, Firefox и IE.
хром:
Fire Fox:
IE:
можно увидетьtoFixed()
Округление не точное на хроме, фаерфоксе.
а такжеtoFixed()
В Chrome и Firefox он не округляется банковским округлением, как упоминалось в Интернете.
Правило банковского метода округления: «округлить до пяти. Если число после пяти не равно нулю, прибавьте единицу. Если число после пяти равно нулю, см. четно-нечетное. Если оно четное до пяти, оно должно округлить. Если до пяти нечетно, прибавьте единицу».
Например, банковское округление равно(2.55).toFixed(1) = 2.5
,(3.55).toFixed(1) = 3.5
выше не совпадает.
Так почему же это происходит?Начнем с определения toFixed.спецификация ecmascriptПредставление toFixed:
Выполните шаги, показанные на рисунке выше, чтобы продемонстрировать(2.55).toFixed(1) = 2.5
процесс обработки.
x равно 2,55, что меньше, чем, f равно 1, так чтоТочное математическое значение максимально близко к нулю, принимая n равным 25 и n равным 26,
Вы можете видеть, что ближайший к нулю должен быть -0,04999... , поэтому n равно 25, затем m равно 25, k равно 2,равно 1, поэтому a равно 2, затем b равно 5, поэтому(2.55).toFixed(1)
Результат2.5
.
Как можно заметить(2.55).toFixed(1)
Результат2.5
вместо2.6
,Да... причина, в то время какпочему не равно, причина испектрда, ты можешь меня видетьэтот столбец.
Но в браузере IE выполнитеа такжеРезультат такой же, как при выполнении в chrome и firefox. Здесь можно только сделать вывод, что toFixed, определенный в браузере IE, не соответствует спецификации ecmascript. Конкретная причина пока не ясна. Если вы знаете, вы можете оставить сообщение в комментариях, спасибо.
решить
Предполагая, что число, которое нужно округлить, равно числу, чтобы сохранить n знаков после запятой, вы можете сначала использовать, затем используйтеMath.round()
собрали и окончательно удалили, который косвенно реализует округление. Кроме тогоtoFixed()
Также есть функция автоматического заполнения нулями, которую необходимо реализовать, поэтому нижеследующее просто инкапсулирует метод toFixed для достижения округления.
function toFixed(number, m) {
if (typeof number !== 'number') {
throw new Error("number不是数字");
}
let result = Math.round(Math.pow(10, m) * number) / Math.pow(10, m);
result = String(result);
if (result.indexOf(".") == -1) {
if(m != 0){
result += ".";
result += new Array(m + 1).join('0');
}
} else {
let arr = result.split('.');
if (arr[1].length < m) {
arr[1] += new Array(m - arr[1].length + 1).join('0')
}
result = arr.join('.')
}
return result
}