Округлить до 2 знаков после запятой (только при необходимости)

Я хотел бы округлить не более 2 десятичных знаков, но только при необходимости.

Входные данные:

10
1.7777777
9.1

Выход:

10
1.78
9.1

Как я могу сделать это в JavaScript?

97 ответов

Решение

Использование Math.round(num * 100) / 100

Если значение является типом текста:

parseFloat("123.456").toFixed(2);

Если значение является числом:

var numb = 123.23454;
numb = numb.toFixed(2);

Недостатком является то, что такие значения, как 1,5, будут давать "1,50" в качестве выходных данных. Исправление, предложенное @minitech:

var numb = 1.5;
numb = +numb.toFixed(2);
// Note the plus sign that drops any "extra" zeroes at the end.
// It changes the result (which is a string) into a number again (think "0 + foo"),
// which means that it uses only as many digits as necessary.

Это похоже на Math.round это лучшее решение. Но это не так! В некоторых случаях это НЕ будет округлено правильно:

Math.round(1.005 * 1000)/1000 // Returns 1 instead of expected 1.01!

toFixed () также НЕ будет правильно округляться в некоторых случаях (протестировано в Chrome v.55.0.2883.87)!

Примеры:

parseFloat("1.555").toFixed(2); // Returns 1.55 instead of 1.56.
parseFloat("1.5550").toFixed(2); // Returns 1.55 instead of 1.56.
// However, it will return correct result if you round 1.5551.
parseFloat("1.5551").toFixed(2); // Returns 1.56 as expected.

1.3555.toFixed(3) // Returns 1.355 instead of expected 1.356.
// However, it will return correct result if you round 1.35551.
1.35551.toFixed(2); // Returns 1.36 as expected.

Я думаю, это потому, что 1.555 - это что-то вроде плавающего 1.55499994 за кулисами.

Решение 1 - использовать скрипт с необходимым алгоритмом округления, например:

function roundNumber(num, scale) {
  if(!("" + num).includes("e")) {
    return +(Math.round(num + "e+" + scale)  + "e-" + scale);
  } else {
    var arr = ("" + num).split("e");
    var sig = ""
    if(+arr[1] + scale > 0) {
      sig = "+";
    }
    return +(Math.round(+arr[0] + "e" + sig + (+arr[1] + scale)) + "e-" + scale);
  }
}

https://plnkr.co/edit/uau8BlS1cqbvWPCHJeOy?p=preview

Решение 2 состоит в том, чтобы избежать вычислений внешнего интерфейса и получить округленные значения от внутреннего сервера.

Ты можешь использовать

function roundToTwo(num) {    
    return +(Math.round(num + "e+2")  + "e-2");
}

Я нашел это на MDN. Их путь позволяет избежать проблемы с 1.005, о которой упоминалось.

roundToTwo(1.005)
1.01
roundToTwo(10)
10
roundToTwo(1.7777777)
1.78
roundToTwo(9.1)
9.1
roundToTwo(1234.5678)
1234.57

В общем, округление выполняется путем масштабирования: round(num / p) * p

Использование экспоненциальной записи правильно обрабатывает округление чисел +ve. Однако этот метод не может правильно округлить все крайние случаи.

function round(num, precision = 2) {
 var scaled = Math.round(num + "e" + precision);
 return Number(scaled + "e" + -precision);
}

// testing some edge cases
console.log( round(1.005, 2) );  // 1.01 correct
console.log( round(2.175, 2) );  // 2.18 correct
console.log( round(5.015, 2) );  // 5.02 correct

console.log( round(-1.005, 2) );  // -1    wrong
console.log( round(-2.175, 2) );  // -2.17 wrong
console.log( round(-5.015, 2) );  // -5.01 wrong

Здесь также есть одна функция, которую я написал для правильного арифметического округления. Вы можете проверить это сами.

/**
 * MidpointRounding away from zero ('arithmetic' rounding)
 * Uses a half-epsilon for correction. (This offsets IEEE-754
 * half-to-even rounding that was applied at the edge cases).
 */

function RoundCorrect(num, precision = 2) {
 // half epsilon to correct edge cases.
 var c = 0.5 * Number.EPSILON * num;
// var p = Math.pow(10, precision); //slow
 var p = 1; while (precision--> 0) p *= 10;
 if (num < 0)
  p *= -1;
 return Math.round((num + c) * p) / p;
}

// testing some edge cases
console.log(RoundCorrect(1.005, 2));  // 1.01 correct
console.log(RoundCorrect(2.175, 2));  // 2.18 correct
console.log(RoundCorrect(5.015, 2));  // 5.02 correct

console.log(RoundCorrect(-1.005, 2));  // -1.01 correct
console.log(RoundCorrect(-2.175, 2));  // -2.18 correct
console.log(RoundCorrect(-5.015, 2));  // -5.02 correct

Ответ MarkG является правильным. Вот общее расширение для любого количества десятичных знаков.

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

Использование:

var n = 1.7777;    
n.round(2); // 1.78

Модульный тест:

it.only('should round floats to 2 places', function() {

  var cases = [
    { n: 10,      e: 10,    p:2 },
    { n: 1.7777,  e: 1.78,  p:2 },
    { n: 1.005,   e: 1.01,  p:2 },
    { n: 1.005,   e: 1,     p:0 },
    { n: 1.77777, e: 1.8,   p:1 }
  ]

  cases.forEach(function(testCase) {
    var r = testCase.n.round(testCase.p);
    assert.equal(r, testCase.e, 'didn\'t get right number');
  });
})

Вы должны использовать:

Math.round( num * 100 + Number.EPSILON ) / 100

Кажется, никто не знает о Number.EPSILON,

Также стоит отметить, что это нестранность JavaScript, как утверждают некоторые люди.

Это просто способ, которым числа с плавающей запятой работают в компьютере. Как и в 99% языков программирования, JavaScript не имеетсамодельных чисел с плавающей точкой; для этого он использует CPU/FPU. Компьютер использует двоичный код, а в двоичном коде нет таких чисел, как 0.1, но просто двоичное приближение для этого. Зачем? По той же причине нельзя записать 1/3 в десятичном виде: его значение равно 0,33333333... с бесконечностью трех.

Вот идиNumber.EPSILON, Это число представляет собой разницу между 1 иследующим числом, существующим в числах с плавающей запятой двойной точности.Вот и все: между ними нет номера1и 1 +Number.EPSILON ,

РЕДАКТИРОВАТЬ:

Как просили в комментариях, давайте проясним одну вещь: добавление Number.EPSILON имеет значение только тогда, когда значение округления является результатом арифметической операции, так как оно может проглотить некоторую дельту ошибки с плавающей запятой.

Это не полезно, когда значение исходит из прямого источника (например, литерал, пользовательский ввод или датчик).

Этот вопрос сложный.

Предположим, у нас есть функция, roundTo2DP(num), который принимает в качестве аргумента число с плавающей точкой и возвращает значение, округленное до 2 десятичных знаков. Что должно оценивать каждое из этих выражений?

  • roundTo2DP(0.014999999999999999)
  • roundTo2DP(0.0150000000000000001)
  • roundTo2DP(0.015)

"Очевидный" ответ заключается в том, что первый пример должен округляться до 0,01 (потому что он ближе к 0,01, чем до 0,02), в то время как два других должны округляться до 0,02 (потому что 0,0150000000000000001 ближе к 0,02, чем к 0,01, а также потому, что 0,015 находится точно на полпути между их и есть математическое соглашение, что такие числа округляются).

Уловка, о которой вы могли догадаться, заключается в том, что roundTo2DP не может быть реализовано, чтобы дать эти очевидные ответы, потому что все три числа, переданные ему, являются одним и тем же номером. Двоичные числа с плавающей точкой IEEE 754 (тип, используемый в JavaScript) не могут точно представлять большинство нецелых чисел, и поэтому все три числовых литерала выше округляются до ближайшего действительного числа с плавающей запятой. Это число, как это бывает, точно

0,01499999999999999944488848768742172978818416595458984375

что ближе к 0,01, чем к 0,02.

Вы можете видеть, что все три числа одинаковы на консоли браузера, в оболочке Node или другом интерпретаторе JavaScript. Просто сравните их:

> 0.014999999999999999 === 0.0150000000000000001
true

Поэтому, когда я пишу m = 0.0150000000000000001, точное значение m что я в конечном итоге ближе к 0.01 чем это 0.02, И все же, если я преобразую m в строку...

> var m = 0.0150000000000000001;
> console.log(String(m));
0.015
> var m = 0.014999999999999999;
> console.log(String(m));
0.015

... Я получаю 0,015, что должно округляться до 0,02, и это заметно не то число с 56 десятичными разрядами, о котором я ранее говорил, что все эти числа точно равны. Так что это за темная магия?

Ответ можно найти в спецификации ECMAScript, в разделе 7.1.12.1: ToString применяется к типу Number. Здесь изложены правила для преобразования некоторого числа m в строку. Ключевой частью является точка 5, в которой генерируется целое число s, цифры которого будут использоваться в строковом представлении m:

пусть n, k и s будут целыми числами, так что k ≥ 1, 10 k -1s <10 k, числовое значение для s × 10 n - k равно m, а k настолько мало, насколько это возможно. Обратите внимание, что k - это количество цифр в десятичном представлении s, что s не делится на 10, и что младшая значащая цифра s не обязательно определяется по этим критериям однозначно.

Ключевой частью здесь является требование, чтобы " k было как можно меньше". То, что составляет это требование, является требованием, которое, учитывая число m, значение String(m) должно иметь наименьшее возможное количество цифр, при этом удовлетворяя требованию Number(String(m)) === m, Поскольку мы уже знаем, что 0.015 === 0.0150000000000000001 теперь понятно почему String(0.0150000000000000001) === '0.015' должно быть правдой.

Конечно, никто из этого обсуждения прямо не ответил, что roundTo2DP(m) должен вернуться. Если m Точное значение равно 0,01499999999999999944488848768742172978818416595458984375, но его строковое представление равно 0,015, тогда каков правильный ответ - математически, практически, философски или как угодно - когда мы округляем его до двух десятичных знаков?

На этот вопрос нет однозначного правильного ответа. Это зависит от вашего варианта использования. Вы, вероятно, хотите уважать представление String и округлять вверх, когда:

  • Представляемое значение является дискретным по своей природе, например, количество валюты в валюте с 3 десятичными знаками, например, в динарах. В этом случае истинное значение числа, такого как 0,015, равно 0,015, а представление 0,0149999999..., которое оно получает в двоичной переменной с плавающей запятой, является ошибкой округления. (Конечно, многие будут разумно утверждать, что вы должны использовать десятичную библиотеку для обработки таких значений и никогда не представлять их как двоичные числа с плавающей запятой.)
  • Значение было введено пользователем. В этом случае, опять же, точное введенное десятичное число является более "истинным", чем ближайшее двоичное представление с плавающей запятой.

С другой стороны, вы, вероятно, хотите уважать двоичное значение с плавающей запятой и округлять в меньшую сторону, когда ваше значение по непрерывной шкале - например, если это считывание с датчика.

Эти два подхода требуют различного кода. Чтобы уважать строковое представление числа, мы можем (с небольшим количеством достаточно тонкого кода) реализовать наше собственное округление, которое действует непосредственно на строковое представление, цифра за цифрой, используя тот же алгоритм, который вы использовали в школе, когда вы научили округлять числа. Ниже приведен пример, в котором соблюдается требование ОП о представлении числа в 2 десятичных знака "только при необходимости" путем удаления конечных нулей после десятичной точки; вам, конечно, может понадобиться настроить его под ваши конкретные потребности.

/**
 * Converts num to a decimal string (if it isn't one already) and then rounds it
 * to at most dp decimal places.
 *
 * For explanation of why you'd want to perform rounding operations on a String
 * rather than a Number, see http://stackru.com/a/38676273/1709587
 *
 * @param {(number|string)} num
 * @param {number} dp
 * @return {string}
 */
function roundStringNumberWithoutTrailingZeroes (num, dp) {
    if (arguments.length != 2) throw new Error("2 arguments required");

    num = String(num);
    if (num.indexOf('e+') != -1) {
        // Can't round numbers this large because their string representation
        // contains an exponent, like 9.99e+37
        throw new Error("num too large");
    }
    if (num.indexOf('.') == -1) {
        // Nothing to do
        return num;
    }

    var parts = num.split('.'),
        beforePoint = parts[0],
        afterPoint = parts[1],
        shouldRoundUp = afterPoint[dp] >= 5,
        finalNumber;

    afterPoint = afterPoint.slice(0, dp);
    if (!shouldRoundUp) {
        finalNumber = beforePoint + '.' + afterPoint;
    } else if (/^9+$/.test(afterPoint)) {
        // If we need to round up a number like 1.9999, increment the integer
        // before the decimal point and discard the fractional part.
        finalNumber = Number(beforePoint)+1;
    } else {
        // Starting from the last digit, increment digits until we find one
        // that is not 9, then stop
        var i = dp-1;
        while (true) {
            if (afterPoint[i] == '9') {
                afterPoint = afterPoint.substr(0, i) +
                             '0' +
                             afterPoint.substr(i+1);
                i--;
            } else {
                afterPoint = afterPoint.substr(0, i) +
                             (Number(afterPoint[i]) + 1) +
                             afterPoint.substr(i+1);
                break;
            }
        }

        finalNumber = beforePoint + '.' + afterPoint;
    }

    // Remove trailing zeroes from fractional part before returning
    return finalNumber.replace(/0+$/, '')
}

Пример использования:

> roundStringNumberWithoutTrailingZeroes(1.6, 2)
'1.6'
> roundStringNumberWithoutTrailingZeroes(10000, 2)
'10000'
> roundStringNumberWithoutTrailingZeroes(0.015, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.015000', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(1, 1)
'1'
> roundStringNumberWithoutTrailingZeroes('0.015', 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes(0.01499999999999999944488848768742172978818416595458984375, 2)
'0.02'
> roundStringNumberWithoutTrailingZeroes('0.01499999999999999944488848768742172978818416595458984375', 2)
'0.01'

Вышеприведенная функция - это, вероятно, то, что вы хотите использовать, чтобы пользователи никогда не видели, что введенные ими числа неправильно округляются.

(В качестве альтернативы вы также можете попробовать библиотеку round10, которая предоставляет функцию с аналогичным поведением и имеет совершенно другую реализацию.)

Но что, если у вас есть второй тип числа - значение, взятое из непрерывной шкалы, где нет оснований думать, что приближенные десятичные представления с меньшим количеством десятичных знаков более точны, чем те, у которых больше? В этом случае мы не хотим уважать представление String, потому что это представление (как объяснено в спецификации) уже округлено; мы не хотим ошибаться, говоря: "0,014999999...375 округляет до 0,015, что округляет до 0,02, поэтому 0,014999999...375 округляет до 0,02".

Здесь мы можем просто использовать встроенный toFixed метод. Обратите внимание, что по телефону Number() на строке, возвращенной toFixed мы получаем число, у которого строковое представление не имеет конечных нулей (благодаря тому, как JavaScript вычисляет строковое представление числа, обсуждавшееся ранее в этом ответе).

/**
 * Takes a float and rounds it to at most dp decimal places. For example
 *
 *     roundFloatNumberWithoutTrailingZeroes(1.2345, 3)
 *
 * returns 1.234
 *
 * Note that since this treats the value passed to it as a floating point
 * number, it will have counterintuitive results in some cases. For instance,
 * 
 *     roundFloatNumberWithoutTrailingZeroes(0.015, 2)
 *
 * gives 0.01 where 0.02 might be expected. For an explanation of why, see
 * http://stackru.com/a/38676273/1709587. You may want to consider using the
 * roundStringNumberWithoutTrailingZeroes function there instead.
 *
 * @param {number} num
 * @param {number} dp
 * @return {number}
 */
function roundFloatNumberWithoutTrailingZeroes (num, dp) {
    var numToFixedDp = Number(num).toFixed(dp);
    return Number(numToFixedDp);
}

Рассматривать .toFixed() а также .toPrecision():

http://www.javascriptkit.com/javatutors/formatnumber.shtml

Можно использовать .toFixed(NumberOfDecimalPlaces),

var str = 10.234.toFixed(2); // => '10.23'
var number = Number(str); // => 10.23

Вот простой способ сделать это:

Math.round(value * 100) / 100

Вы можете пойти дальше и сделать отдельную функцию, чтобы сделать это для вас, хотя:

function roundToTwo(value) {
    return(Math.round(value * 100) / 100);
}

Тогда вы просто передадите значение.

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

function myRound(value, places) {
    var multiplier = Math.pow(10, places);

    return (Math.round(value * multiplier) / multiplier);
}

Точный метод округления. Источник: Мозилла

(function(){

    /**
     * Decimal adjustment of a number.
     *
     * @param   {String}    type    The type of adjustment.
     * @param   {Number}    value   The number.
     * @param   {Integer}   exp     The exponent (the 10 logarithm of the adjustment base).
     * @returns {Number}            The adjusted value.
     */
    function decimalAdjust(type, value, exp) {
        // If the exp is undefined or zero...
        if (typeof exp === 'undefined' || +exp === 0) {
            return Math[type](value);
        }
        value = +value;
        exp = +exp;
        // If the value is not a number or the exp is not an integer...
        if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0)) {
            return NaN;
        }
        // Shift
        value = value.toString().split('e');
        value = Math[type](+(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp)));
        // Shift back
        value = value.toString().split('e');
        return +(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp));
    }

    // Decimal round
    if (!Math.round10) {
        Math.round10 = function(value, exp) {
            return decimalAdjust('round', value, exp);
        };
    }
    // Decimal floor
    if (!Math.floor10) {
        Math.floor10 = function(value, exp) {
            return decimalAdjust('floor', value, exp);
        };
    }
    // Decimal ceil
    if (!Math.ceil10) {
        Math.ceil10 = function(value, exp) {
            return decimalAdjust('ceil', value, exp);
        };
    }
})();

Примеры:

// Round
Math.round10(55.55, -1); // 55.6
Math.round10(55.549, -1); // 55.5
Math.round10(55, 1); // 60
Math.round10(54.9, 1); // 50
Math.round10(-55.55, -1); // -55.5
Math.round10(-55.551, -1); // -55.6
Math.round10(-55, 1); // -50
Math.round10(-55.1, 1); // -60
Math.round10(1.005, -2); // 1.01 -- compare this with Math.round(1.005*100)/100 above
// Floor
Math.floor10(55.59, -1); // 55.5
Math.floor10(59, 1); // 50
Math.floor10(-55.51, -1); // -55.6
Math.floor10(-51, 1); // -60
// Ceil
Math.ceil10(55.51, -1); // 55.6
Math.ceil10(51, 1); // 60
Math.ceil10(-55.59, -1); // -55.5
Math.ceil10(-59, 1); // -50

Ни один из найденных здесь ответов не является правильным. @stinkycheeseman попросил округлить, вы все округлили число.

Чтобы округлить, используйте это:

Math.ceil(num * 100)/100;

Это может помочь вам:

var result = (Math.round(input*100)/100);

Для получения дополнительной информации, вы можете посмотреть по этой ссылке

Math.round(num) против num.toFixed(0) и несоответствия браузера

Если вы используете библиотеку lodash, вы можете использовать метод lodash round, как показано ниже.

_.round(number, precision)

Например:

_.round(1.7777777, 2) = 1.78

Для меня Math.round() не давал правильного ответа. Я нашел toFixed(2) работает лучше. Ниже приведены примеры обоих:

console.log(Math.round(43000 / 80000) * 100); // wrong answer

console.log(((43000 / 80000) * 100).toFixed(2)); // correct answer

Используйте эту функцию Number(x).toFixed(2);

+(10).toFixed(2); // = 10
+(10.12345).toFixed(2); // = 10.12

(10).toFixed(2); // = 10.00
(10.12345).toFixed(2); // = 10.12

Попробуйте это облегченное решение:

function round(x, digits){
  return parseFloat(x.toFixed(digits))
}

 round(1.222,  2) ;
 // 1.22
 round(1.222, 10) ;
 // 1.222

Есть несколько способов сделать это. Для таких, как я, вариант Лодаша

function round(number, precision) {
    var pair = (number + 'e').split('e')
    var value = Math.round(pair[0] + 'e' + (+pair[1] + precision))
    pair = (value + 'e').split('e')
    return +(pair[0] + 'e' + (+pair[1] - precision))
}

Использование:

round(0.015, 2) // 0.02
round(1.005, 2) // 1.01

Если ваш проект использует jQuery или lodash, вы также можете найти round метод в библиотеках.

Обновление 1

Я удалил вариант n.toFixed(2)потому что это не правильно. Спасибо @avalanche1

2017
Просто используйте нативный код .toFixed()

number = 1.2345;
number.toFixed(2) // "1.23"

Если вам нужно быть строгим и добавлять цифры только при необходимости, он может использовать replace

number = 1; // "1"
number.toFixed(5).replace(/\.?0*$/g,'');

Другое простое решение (без написания какой-либо функции) может использовать toFixed(), а затем снова преобразовать в float.

      For Example:
var objNumber = 1201203.1256546456;
objNumber = parseFloat(objNumber.toFixed(2))

Начиная с ES6, существует "правильный" способ (без переопределения статики и создания обходных путей) сделать это с помощью toPrecision.

var x = 1.49999999999;
console.log(x.toPrecision(4));
console.log(x.toPrecision(3));
console.log(x.toPrecision(2));

var y = Math.PI;
console.log(y.toPrecision(6));
console.log(y.toPrecision(5));
console.log(y.toPrecision(4));

var z = 222.987654
console.log(z.toPrecision(6));
console.log(z.toPrecision(5));
console.log(z.toPrecision(4));

Сохраните тип как целое число для последующей сортировки или других математических операций:

Math.round(1.7777777 * 100)/100

1,78

// Round up!
Math.ceil(1.7777777 * 100)/100 

1,78

// Round down!
Math.floor(1.7777777 * 100)/100

1,77

Или преобразовать в строку:

(1.7777777).toFixed(2)

"1,77"

Самый простой подход - использовать toFixed, а затем удалить конечные нули с помощью функции Number:

const number = 15.5;
Number(number.toFixed(2)); // 15.5
const number = 1.7777777;
Number(number.toFixed(2)); // 1.78

Один из способов добиться такого округления только при необходимости - использовать Number.prototype.toLocaleString ():

myNumber.toLocaleString('en', {maximumFractionDigits:2, useGrouping:false})

Это обеспечит именно тот результат, который вы ожидаете, но в виде строк. Вы все еще можете преобразовать их обратно в числа, если это не тот тип данных, который вы ожидаете.

MarkG и Lavamantis предложили гораздо лучшее решение, чем то, которое было принято. Жаль, что они не получают больше голосов!

Вот функция, которую я использую для решения десятичных чисел с плавающей запятой, также основанная на MDN. Это даже более универсально (но менее кратко), чем решение Lavamantis:

function round(value, exp) {
  if (typeof exp === 'undefined' || +exp === 0)
    return Math.round(value);

  value = +value;
  exp  = +exp;

  if (isNaN(value) || !(typeof exp === 'number' && exp % 1 === 0))
    return NaN;

  // Shift
  value = value.toString().split('e');
  value = Math.round(+(value[0] + 'e' + (value[1] ? (+value[1] + exp) : exp)));

  // Shift back
  value = value.toString().split('e');
  return +(value[0] + 'e' + (value[1] ? (+value[1] - exp) : -exp));
}

Используйте это с:

round(10.8034, 2);      // Returns 10.8
round(1.275, 2);        // Returns 1.28
round(1.27499, 2);      // Returns 1.27
round(1.2345678e+2, 2); // Returns 123.46

По сравнению с решением Lavamantis, мы можем сделать...

round(1234.5678, -2); // Returns 1200
round("123.45");      // Returns 123

Это может работать для вас,

Math.round(num * 100)/100;

знать разницу между фиксированным и круглым. Вы можете взглянуть на Math.round(num) против num.toFixed(0) и несоответствия браузера.

Это самое простое, более элегантное решение (а я лучший в мире;):

function roundToX(num, X) {    
    return +(Math.round(num + "e+"+X)  + "e-"+X);
}
//roundToX(66.66666666,2) => 66.67
//roundToX(10,2) => 10
//roundToX(10.904,2) => 10.9
var roundUpto = function(number, upto){
    return Number(number.toFixed(upto));
}
roundUpto(0.1464676, 2);

toFixed(2) здесь 2 - количество цифр, до которого мы хотим округлить это число.

После прохождения различных итераций всех возможных способов достижения по-настоящему точной точности округления десятичных чисел становится ясно, что наиболее точным и эффективным решением является использование Number.EPSILON. Это обеспечивает истинное математическое решение проблемы математической точности с плавающей запятой. Его можно легко заполнить, как показано здесь: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Number/EPSILON для поддержки всех последних оставшихся пользователей IE (тогда, возможно, мы должен прекратить делать это).

Адаптировано из решения, представленного здесь: /questions/36768445/formatirovanie-chisla-s-tochnostyu-do-dvuh-desyatichnyih-znakov-v-javascript/36768463#36768463

Простое решение для снижения, которое обеспечивает точное округление, настил и потолок с десятичной дробью, с необязательной переменной точности без добавления всей библиотеки.

var DecimalPrecision = (function(){
        if (Number.EPSILON === undefined) {
            Number.EPSILON = Math.pow(2, -52);
        }
        this.round = function(n, p=2){
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            if(n < 0)
                o *= -1;
            return Math.round((n + r) * o) / o;
        }
        this.ceil = function(n, p=2){
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            if(n < 0)
                o *= -1;
            return Math.ceil((n + r) * o) / o;
        }
        this.floor = function(n, p=2){
            let r = 0.5 * Number.EPSILON * n;
            let o = 1; while(p-- > 0) o *= 10;
            if(n < 0)
                o *= -1;
            return Math.floor((n + r) * o) / o;
        }
        return this;
    })();
    console.log(DecimalPrecision.round(1.005));
    console.log(DecimalPrecision.ceil(1.005));
    console.log(DecimalPrecision.floor(1.005));
    console.log(DecimalPrecision.round(1.0049999));
    console.log(DecimalPrecision.ceil(1.0049999));
    console.log(DecimalPrecision.floor(1.0049999));
    console.log(DecimalPrecision.round(2.175495134384,7));
    console.log(DecimalPrecision.round(2.1753543549,8));
    console.log(DecimalPrecision.round(2.1755465135353,4));

Другие вопросы по тегам