Javascript - Округление от 1675 до 1,67 - По умолчанию округляется до 1,68 - PullRequest
0 голосов
/ 09 ноября 2019

Есть идеи, как округлить 1.675 до 1.67?

По умолчанию оно округляется до 1.68:

Math.round(1.675 * 100) / 100; // 1.68

Кстати, если число равно 1.676, он должен все еще округляться до 1.68, как и ожидалось.

1 Ответ

0 голосов
/ 09 ноября 2019

Нам нужно пойти глубже, чтобы оно появилось первым…

ECMA-262 определяет Math.round() следующим образом:

Возвращает числовое значение, которое являетсяближайший к аргументу и равен математическому целому числу. Если два значения целых чисел одинаково близки к аргументу, то результатом является значение числа, которое ближе к + ∞. Если аргумент уже является целым числом, результатом является сам аргумент.

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

Math.round(1.674 * 100) / 100;  //  1.67
Math.round(1.675 * 100) / 100;  //  1.68 (wrong)
Math.round(1.676 * 100) / 100;  //  1.68

Math.round(-1.674 * 100) / 100; // -1.67
Math.round(-1.675 * 100) / 100; // -1.67
Math.round(-1.676 * 100) / 100; // -1.68

Посмотрите, как это уже работает, как вы ожидаете для отрицательных чисел!

Если выхотите изменить 1.675 округленное значение, вы не можете использовать Math.floor(), так как это изменит все остальные результаты:

Math.floor(1.674 * 100) / 100;  //  1.67
Math.floor(1.675 * 100) / 100;  //  1.67
Math.floor(1.676 * 100) / 100;  //  1.67 (wrong)

Math.floor(-1.674 * 100) / 100; // -1.68 (wrong)
Math.floor(-1.675 * 100) / 100; // -1.68 (wrong)
Math.floor(-1.676 * 100) / 100; // -1.68

Мое решение будет использовать эту специфику Javascript, которую он ищет ближайшее значение к + ∞ .

  1. Возьмите ваше число 1.675
  2. Получите его абсолютное значение 1.675 (это для отрицательных чисел)
  3. Отрицание -1.675
  4. Используйте round(), чтобы получить наиболее близкое значение к + ∞ -1.67
  5. Отклонить его обратно, если изначально это было положительное число 1.67

Подтверждение концепции:

function _round(value, precision) {
  var shift = Math.pow(10, precision);
  var negateBack = Math.abs(value) / -value;
  return Math.round(Math.abs(value) * -1 * shift) / shift * negateBack;
}

_round(1.674, 2);  //  1.67
_round(1.675, 2);  //  1.67
_round(1.676, 2);  //  1.68

_round(-1.674, 2); // -1.67
_round(-1.675, 2); // -1.67
_round(-1.676, 2); // -1.68
...