5

JavaScript: Округление до двух знаков после запятой

11

Проблема с округлением в JavaScript

Я столкнулся с проблемой при работе с округлением в JavaScript. У меня есть следующий код:

var discount = Math.round(100 - (price / listprice) * 100);

Этот код округляет значение до целого числа. Однако мне необходимо, чтобы результат возвращал хотя бы два знака после запятой.

Как я могу изменить этот код, чтобы получить результат с двумя десятичными знаками, если это необходимо? Заранее спасибо за помощь!

5 ответ(ов)

10

Примечание - Смотрите Редактирование 4, если важна точность до 3 знаков после запятой

var discount = (price / listprice).toFixed(2);

Метод toFixed будет округлять значение в зависимости от знаков после 2-го знака.

Пример: http://jsfiddle.net/calder12/tv9HY/

Документация: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/toFixed

Редактирование - Как уже упомянули другие, этот метод преобразует результат в строку. Чтобы избежать этого:

var discount = +((price / listprice).toFixed(2));

Редактирование 2 - Как также отмечалось в комментариях, эта функция может давать ошибки в некоторых случаях, например, для 1.005 она вернет 1.00 вместо 1.01. Если важна такая точность, я нашел вот этот ответ: https://stackoverflow.com/a/32605063/1726511, который хорошо работает со всеми тестами, которые я пробовал.

Но требуется небольшое изменение: функция, приведенная в указанном ответе, возвращает целые числа, когда округляет до одного, так что, например, 99.004 вернет 99 вместо 99.00, что не совсем удобно для отображения цен.

Редактирование 3 - Похоже, что использование toFixed в самом возврате все еще портило некоторые числа, это финальное редактирование, кажется, работает. Уф, столько переработок!

var discount = roundTo((price / listprice), 2);

function roundTo(n, digits) {
  if (digits === undefined) {
    digits = 0;
  }

  var multiplicator = Math.pow(10, digits);
  n = parseFloat((n * multiplicator).toFixed(11));
  var test =(Math.round(n) / multiplicator);
  return +(test.toFixed(digits));
}

Смотрите пример на Fiddle: https://jsfiddle.net/calder12/3Lbhfy5s/

Редактирование 4 - Вы меня убиваете. Редактирование 3 не справляется с отрицательными числами, не углубляясь в детали, проще сделать отрицательное число положительным перед округлением, а затем вернуть его в исходное состояние.

function roundTo(n, digits) {
    var negative = false;
    if (digits === undefined) {
        digits = 0;
    }
    if (n < 0) {
        negative = true;
        n = n * -1;
    }
    var multiplicator = Math.pow(10, digits);
    n = parseFloat((n * multiplicator).toFixed(11));
    n = (Math.round(n) / multiplicator).toFixed(digits);
    if (negative) {
        n = (n * -1).toFixed(digits);
    }
    return n;
}

Fiddle: https://jsfiddle.net/3Lbhfy5s/79/

0

Наилучшим и простым решением, которое я нашёл, является следующее:

function round(value, decimals) {
    return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}
round(1.005, 2); // 1.01

Этот код позволяет округлять число до заданного количества знаков после запятой. В примере round(1.005, 2) результат будет 1.01.

0

Функции Math.round() и .toFixed() предназначены для округления до ближайшего целого числа. Однако, при работе с десятичными числами и использовании метода "умножь и раздели" для Math.round(), или параметра для .toFixed(), вы можете получить неверные результаты. Например, если вы попытаетесь округлить 1.005 с помощью Math.round(1.005 * 100) / 100, вы получите результат 1, а при использовании .toFixed(2) вы получите 1.00, вместо правильного ответа 1.01.

Для решения этой проблемы вы можете использовать следующий код:

Number(Math.round(100 - (price / listprice) * 100 + 'e2') + 'e-2');

Добавьте .toFixed(2), чтобы получить два десятичных знака, которые вам нужны:

Number(Math.round(100 - (price / listprice) * 100 + 'e2') + 'e-2').toFixed(2);

Вы также можете создать функцию, которая будет обрабатывать округление за вас:

function round(value, decimals) {
    return Number(Math.round(value + 'e' + decimals) + 'e-' + decimals);
}

Пример: https://jsfiddle.net/k5tpq3pd/36/

Альтернатива

Вы можете добавить функцию округления к объекту Number, используя прототип. Я бы не рекомендовал добавлять .toFixed(), так как это вернёт строку вместо числа.

Number.prototype.round = function(decimals) {
    return Number((Math.round(this + "e" + decimals) + "e-" + decimals));
}

Использовать это можно так:

var numberToRound = 100 - (price / listprice) * 100;
numberToRound.round(2);
numberToRound.round(2).toFixed(2); // Преобразует в строку с двумя десятичными

Пример: https://jsfiddle.net/k5tpq3pd/35/

Источник: http://www.jacklmoore.com/notes/rounding-in-javascript/

0

Чтобы получить результат с двумя знаками после запятой, вы можете сделать это следующим образом:

var discount = Math.round((100 - (price / listprice) * 100) * 100) / 100;

Значение, которое нужно округлить, умножается на 100, чтобы сохранить первые две цифры, после чего мы делим на 100, чтобы получить окончательный результат.

0

Я думаю, что лучший способ, который я видел, заключается в умножении на 10 в степени количества цифр, затем применении Math.round и, наконец, делении на 10 в степени количества цифр. Вот простая функция, которую я использую в TypeScript:

function roundToXDigits(value: number, digits: number) {
    value = value * Math.pow(10, digits);
    value = Math.round(value);
    value = value / Math.pow(10, digits);
    return value;
}

Или на чистом JavaScript:

function roundToXDigits(value, digits) {
    if (!digits) {
        digits = 2;
    }
    value = value * Math.pow(10, digits);
    value = Math.round(value);
    value = value / Math.pow(10, digits);
    return value;
}

Эта функция принимает число и количество цифр, до которых нужно округлить. Если количество цифр не указано, в JavaScript функция по умолчанию округляет до 2 знаков после запятой.

Чтобы ответить на вопрос, пожалуйста, войдите или зарегистрируйтесь