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

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

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

10
1.7777777
9.1

Выход:

10
1.78
9.1

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

97 ответов

Большая проблема в этой, казалось бы, простой задаче состоит в том, что мы хотим, чтобы она давала психологически ожидаемые результаты, даже если исходные данные содержат минимальные ошибки округления для начала (не упоминая ошибки, которые произойдут в наших расчетах). Если мы знаем, что реальный результат равен ровно 1,005, мы ожидаем, что округление до двух цифр даст 1,01, даже если 1,005 является результатом большого вычисления с множеством ошибок округления в пути.

Проблема становится еще более очевидной при floor() вместо round(), Например, при вырезании всего после двух последних цифр за точкой 33,3 мы, конечно, не ожидаем получить 33,29 в результате, но вот что происходит:

console.log(Math.floor(33.3 * 100) / 100)

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

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

var round = function(num, digits = 2, compensateErrors = 2) {
  if (num < 0) {
    return -this.round(-num, digits, compensateErrors);
  }
  const pow = Math.pow(10, digits);
  return (Math.round(num * pow * (1 + compensateErrors * Number.EPSILON)) / pow);
}

/* --- testing --- */

console.log("Edge cases mentioned in this thread:")
var values = [ 0.015, 1.005, 5.555, 156893.145, 362.42499999999995, 1.275, 1.27499, 1.2345678e+2, 2.175, 5.015, 58.9 * 0.15 ];
values.forEach((n) => {
  console.log(n + " -> " + round(n));
  console.log(-n + " -> " + round(-n));
});

console.log("\nFor numbers which are so large that rounding cannot be performed anyway within computation precision, only string-based computation can help.")
console.log("Standard: " + round(1e+19));
console.log("Compensation = 1: " + round(1e+19, 2, 1));
console.log("Effectively no compensation: " + round(1e+19, 2, 0.4));

Примечание: Internet Explorer не знает Number.EPSILON, Если вы все еще не можете его поддержать, вы можете использовать прокладку или просто определить константу самостоятельно для этого конкретного семейства браузеров.

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

Например:

1 должен вывести $ 1

1.1 должен вывести $1.10

1.01 должен вывести 1.01 доллара.

Предполагая, что сумма - это число:

const formatAmount = (amount) => amount % 1 === 0 ? amount : amount.toFixed(2);

Если сумма не является числом, используйте parseFloat(количество), чтобы преобразовать ее в число.

Небольшая модификация этого ответа, который, кажется, работает хорошо.

Функция

function roundToStep(value, stepParam) {
   var step = stepParam || 1.0;
   var inv = 1.0 / step;
   return Math.round(value * inv) / inv;
}

Применение

roundToStep(2.55) = 3
roundToStep(2.55, 0.1) = 2.6
roundToStep(2.55, 0.01) = 2.55

Начиная с примера, предложенного для PrecisionRound, который я нашел в MDN (это событие для 1,005 повторений 1, а не 1,01), я пишу пользовательский PrecisionRound, который управляет случайным числом точности, а для 1,005 возвращает 1,01.

Это функция:

function precisionRound(number, precision)
{
  if(precision < 0)
  {
    var factor = Math.pow(10, precision);
    return Math.round(number * factor) / factor;
  }
  else
    return +(Math.round(number + "e+"+precision)  + "e-"+precision);
}

console.log(precisionRound(1234.5678, 1));  // output: 1234.6
console.log(precisionRound(1234.5678, -1)); // output: 1230
console.log(precisionRound(1.005, 2));      // output: 1.01
console.log(precisionRound(1.0005, 2));     // output: 1
console.log(precisionRound(1.0005, 3));     // output: 1.001
console.log(precisionRound(1.0005, 4));     // output: 1.0005

Для TypeScript:

public static precisionRound(number: number, precision: number)
{
  if (precision < 0)
  {
    let factor = Math.pow(10, precision);
    return Math.round(number * factor) / factor;
  }
  else
    return +(Math.round(Number(number + "e+" + precision)) +
      "e-" + precision);
}

Вот функция, которую я придумал, чтобы сделать "округление вверх". Я использовал double Math.round для компенсации неточного умножения JavaScript, поэтому 1.005 будет правильно округлено до 1.01.

function myRound(number, decimalplaces){
    if(decimalplaces > 0){
        var multiply1 = Math.pow(10,(decimalplaces + 4));
        var divide1 = Math.pow(10, decimalplaces);
        return Math.round(Math.round(number * multiply1)/10000 )/divide1;
    }
    if(decimalplaces < 0){
        var divide2 = Math.pow(10, Math.abs(decimalplaces));
        var multiply2 = Math.pow(10, Math.abs(decimalplaces));
        return Math.round(Math.round(number / divide2) * multiply2);
    }
    return Math.round(number);
}

Функция с читаемыми параметрами гораздо более интуитивно понятна:

      function round_number(options) {
    const places = 10**options.decimal_places;
    const res = Math.round(options.number * places)/places;
    return(res)
}

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

      round_number({
    number : 0.5555555555555556,
    decimal_places : 3
})

0.556

Правильно работайте с положительными, отрицательными и большими числами

      function Round(value) {
    const neat = +(Math.abs(value).toPrecision(15));
    const rounded = Math.round(neat * 100) / 100;

    return rounded * Math.sign(value);
}

//0.244 -> 0.24
//0.245 -> 0.25
//0.246 -> 0.25

//-0.244 -> -0.24
//-0.245 -> -0.25
//-0.246 -> -0.25

Просто для записи, метод масштабирования может теоретически возвращать бесконечность, если число и цифры, которые вы хотите округлить, достаточно велики. В JavaScript это не должно быть проблемой, так как максимальное число составляет 1.7976931348623157e+308, но если вы работаете с действительно большими числами или большим количеством десятичных знаков, вы можете попробовать эту функцию вместо этого:

Number.prototype.roundTo = function(digits)
{
    var str = this.toString();
    var split = this.toString().split('e');
    var scientific = split.length > 1;
    var index;
    if (scientific)
    {
        str = split[0];
        var decimal = str.split('.');
        if (decimal.length < 2)
            return this;
        index = decimal[0].length + 1 + digits;
    }
    else
        index = Math.floor(this).toString().length + 1 + digits;
    if (str.length <= index)
        return this;
    var digit = str[index + 1];
    var num = Number.parseFloat(str.substring(0, index));
    if (digit >= 5)
    {
        var extra = Math.pow(10, -digits);
        return this < 0 ? num - extra : num + extra;
    }
    if (scientific)
        num += "e" + split[1];
    return num;
}

Из существующих ответов я нашел другое решение, которое, кажется, прекрасно работает, которое также работает с отправкой в ​​строке и устраняет конечные нули.

function roundToDecimal(string, decimals) {
    return parseFloat(parseFloat(string).toFixed(decimals));
}

Это не принимает во внимание, если вы посылаете какой-то бык.. как "апа", хотя. Или это, вероятно, выдаст ошибку, которая, я думаю, в любом случае является правильным способом, никогда не бывает хорошо скрывать ошибки, которые должны быть исправлены (вызывающей функцией).

Вот мое решение этой проблемы:

function roundNumber(number, precision = 0) {
var num = number.toString().replace(",", "");
var integer, decimal, significantDigit;

if (num.indexOf(".") > 0 && num.substring(num.indexOf(".") + 1).length > precision && precision > 0) {
    integer = parseInt(num).toString();
    decimal = num.substring(num.indexOf(".") + 1);
    significantDigit = Number(decimal.substr(precision, 1));

    if (significantDigit >= 5) {
        decimal = (Number(decimal.substr(0, precision)) + 1).toString();
        return integer + "." + decimal;
    } else {
        decimal = (Number(decimal.substr(0, precision)) + 1).toString();
        return integer + "." + decimal;
    }
}
else if (num.indexOf(".") > 0) {
    integer = parseInt(num).toString();
    decimal = num.substring(num.indexOf(".") + 1);
    significantDigit = num.substring(num.length - 1, 1);

    if (significantDigit >= 5) {
        decimal = (Number(decimal) + 1).toString();
        return integer + "." + decimal;
    } else {            
        return integer + "." + decimal;
    }
} 

return number;
}

Это сработало очень хорошо для меня, когда я хотел всегда округлять до определенного десятичного числа. Ключевым моментом здесь является то, что мы всегда будем округлять с помощью функции Math.ceil.

Вы можете условно выбрать потолок или пол при необходимости.

     /**
     * Possibility to lose precision at large numbers
     * @param number
     * @returns Number number
     */
    var roundUpToNearestHundredth = function(number) {

        // Ensure that we use high precision Number
        number = Number(number);

        // Save the original number so when we extract the Hundredth decimal place we don't bit switch or lose precision
        var numberSave = Number(number.toFixed(0));

        // Remove the "integer" values off the top of the number
        number = number - numberSave;

        // Get the Hundredth decimal places
        number *= 100;

        // Ceil the decimals.  Therefore .15000001 will equal .151, etc.
        number = Math.ceil(number);

        // Put the decimals back into their correct spot
        number /= 100;

        // Add the "integer" back onto the number
        return number + numberSave;

    };

console.log(roundUpToNearestHundredth(6132423.1200000000001))

Есть решение, работающее для всех чисел, попробуйте. Выражение дано ниже.

Math.round((num + 0.00001) * 100) / 100. Try Math.round((1.005 + 0.00001) * 100) / 100 and Math.round((1.0049 + 0.00001) * 100) / 100

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

перейти к amountполе, оно возвращается почти бесконечно. Я попробовалtoFixed() метод, но он не работает в некоторых случаях (например, попробуйте с PI) и, наконец, получил решение, указанное выше.

Общий ответ для всех браузеров и точности:

function round(num, places) {
      if(!places){
       return Math.round(num);
      }

      var val = Math.pow(10, places);
      return Math.round(num * val) / val;
}

round(num, 2);

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

      function roundToDigits(number, digits) {
  return Number(Math.round(Number(number + 'e' + digits)) + 'e-' + digits);
}

Способ исправитьtoFixed()функция будет:

      Number.prototype.toFixed = (prototype => {
    const toFixed = prototype.toFixed;

    // noinspection JSVoidFunctionReturnValueUsed
    return function (fractionDigits) {
        if (!fractionDigits) {
            return toFixed.call(this);
        } else {
            // Avoid binary rounding issues
            fractionDigits = Math.floor(fractionDigits);
            const n = Number(Math.round(Number(+this + 'e' + fractionDigits)) + 'e-' + fractionDigits);
            return toFixed.call(n, fractionDigits);
        }
    };
})(Number.prototype);

Я просто хотел поделиться своим подходом, основанным на ранее упомянутых ответах:

Давайте создадим функцию, которая округляет любое заданное числовое значение до заданного количества десятичных разрядов:

function roundWDecimals(n, decimals) {
    if (!isNaN(parseFloat(n)) && isFinite(n)) {
        if (typeof(decimals) == typeof(undefined)) {
            decimals = 0;
        }
        var decimalPower = Math.pow(10, decimals);
        return Math.round(parseFloat(n) * decimalPower) / decimalPower;
    }
    return NaN;
}

И ввести новый "круглый" метод для чисел-прототипов:

Object.defineProperty(Number.prototype, 'round', {
    enumerable: false,
    value: function(decimals) {
        return roundWDecimals(this, decimals);
    }
});

И вы можете проверить это:

function roundWDecimals(n, decimals) {
    if (!isNaN(parseFloat(n)) && isFinite(n)) {
        if (typeof(decimals) == typeof(undefined)) {
            decimals = 0;
        }
        var decimalPower = Math.pow(10, decimals);
        return Math.round(parseFloat(n) * decimalPower) / decimalPower;
    }
    return NaN;
}
Object.defineProperty(Number.prototype, 'round', {
    enumerable: false,
    value: function(decimals) {
        return roundWDecimals(this, decimals);
    }
});

var roundables = [
    {num: 10, decimals: 2},
    {num: 1.7777777, decimals: 2},
    {num: 9.1, decimals: 2},
    {num: 55.55, decimals: 1},
    {num: 55.549, decimals: 1},
    {num: 55, decimals: 0},
    {num: 54.9, decimals: 0},
    {num: -55.55, decimals: 1},
    {num: -55.551, decimals: 1},
    {num: -55, decimals: 0},
    {num: 1.005, decimals: 2},
    {num: 1.005, decimals: 2},
    {num: 19.8000000007, decimals: 2},
  ],
  table = '<table border="1"><tr><th>Num</th><th>Decimals</th><th>Result</th></tr>';
$.each(roundables, function() {
  table +=
    '<tr>'+
      '<td>'+this.num+'</td>'+
      '<td>'+this.decimals+'</td>'+
      '<td>'+this.num.round(this.decimals)+'</td>'+
    '</tr>'
  ;
});
table += '</table>';
$('.results').append(table);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div class="results"></div>

Функция быстрого помощника, где rounging Округление по умолчанию: let rounding = 4;

let round=(number)=>{ let multiply=Math.pow(10,rounding);  return Math.round(number*multiply)/multiply};

console.log(round(0.040579431));

=> 0,0406

Этот ответ больше о скорости.

var precalculatedPrecisions = [1e0, 1e1, 1e2, 1e3, 1e4, 1e5, 1e6, 1e7, 1e8, 1e9, 1e10];

function round(num, _prec) {
    _precision = precalculatedPrecisions[_prec]
    return Math.round(num * _precision + 1e-14) / _precision ;
}

jsPerf об этом.

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

Код гольфа

Вот версия приведенной выше функции для гольфа:

      r=(n,p=2)=>(e=>((n*e)+.5|0)/e)(10**p) // 37 bytes

Объяснение

Следующие выражения были упрощены:

  • Math.round(n)n+.5|0 (-7 байт)
  • Math.pow(n,m)n**m (-9 байт)

Обратите внимание, чтоMathбиблиотечные функции более эффективны. Если вас интересует игра в гольф с кодом на JavaScript, вам следует прочитать: «Советы и рекомендации по игре в гольф с кодом: как минимизировать код JavaScript».

Предлагаемые ответы, хотя в целом правильные, не учитывают точность переданного числа, что не выражается как требование в исходном вопросе, но может быть требованием в случае научного применения, где 3 отличается от 3,00 (например), поскольку количество десятичных цифр представляет точность прибора, который получил значение, или точность расчета. На самом деле предлагаемые ответы округляют от 3,001 до 3, в то время как при сохранении информации о точности числа должно быть 3,00.

ниже функция, которая учитывает, что

function roundTo(value, decimal) {

    let absValue = Math.abs(value);
    let int = Math.floor(absValue).toString().length;
    let dec = absValue.toString().length - int;
    dec -= (Number.isInteger(absValue) ? 0 : 1);
    return value.toPrecision(int + Math.min(dec, decimal));
  
}

Мое решение рассматривает ввод как строку и использует алгоритм «математического округления» до n цифр: возьмите n цифр и добавьте одну, если цифра n+1 равна 5 или более. Это также позволяет указывать отрицательные цифры, например, округление 123,45 до -1 цифры равно 120. Это также работает с экспоненциальной записью (например, 1.2e-3). Я не измерял его скорость и не думаю, что он был лучшим с точки зрения производительности.

      function safeRound( numInput, numPrecision ) {
    const strNumber = numInput.toString().replace( 'E', 'e' );
    const bSign = '+-'.indexOf( strNumber[ 0 ] ) !== -1;
    const strSign = bSign  ?  strNumber[ 0 ]  :  '';
    const numSign = strSign !== '-'  ?  +1  :  -1;
    const ixExponent = ( ixFound => ixFound !== -1  ?  ixFound  :  strNumber.length )( strNumber.indexOf( 'e' ) );
    const strExponent = strNumber.substr( ixExponent + 1 );
    const numExponent = ixExponent !== strNumber.length  ?  Number.parseInt( strExponent )  :  0;
    const ixDecimal = ( ixFound => ixFound !== -1  ?  ixFound  :  ixExponent )( strNumber.indexOf( '.' ) );
    const strInteger = strNumber.substring( !bSign  ?  0  :  1, ixDecimal );
    const strFraction = strNumber.substring( ixDecimal + 1, ixExponent );
    
    const numPrecisionAdjusted = numPrecision + numExponent;
    const strIntegerKeep = strInteger.substring( 0, strInteger.length + Math.min( 0, numPrecisionAdjusted ) ) + '0'.repeat( -Math.min( 0, numPrecisionAdjusted ) );
    const strFractionKeep = strFraction.substring( 0, Math.max( 0, numPrecisionAdjusted ) );
    const strRoundedDown = strSign + ( strIntegerKeep === ''  ?  '0'  :  strIntegerKeep ) + ( strFractionKeep === ''  ?  ''  :  '.' + strFractionKeep ) + ( strExponent === ''  ?  ''  :  'e' + strExponent );
    
    const chRoundUp = 0 <= numPrecisionAdjusted  ?  strFraction.substr( numPrecisionAdjusted, 1 )  :  ( '0' + strInteger ).substr( numPrecisionAdjusted, 1 );
    const bRoundUp = '5' <= chRoundUp && chRoundUp <= '9';
    const numRoundUp = bRoundUp  ?  numSign * Math.pow( 10, -numPrecision )  :  0;
    
    return Number.parseFloat( strRoundedDown ) + numRoundUp;
}

function safeRoundTest( numInput, numPrecision, strExpected ) {
    const strActual = safeRound( numInput, numPrecision ).toString();
    const bPassed = strActual === strExpected;
    console.log( 'numInput', numInput, 'numPrecision', numPrecision, 'strExpected', strExpected, 'strActual', strActual, 'bPassed', bPassed );
    return bPassed  ?  0  :  1;
}

function safeRoundTests() {
    let numFailed = 0;
    numFailed += safeRoundTest( 0, 0, '0' );
    numFailed += safeRoundTest( '0', 0, '0' );
    numFailed += safeRoundTest( '0.1', 0, '0' );
    numFailed += safeRoundTest( '+0.1', 0, '0' );
    numFailed += safeRoundTest( '-0.1', 0, '0' );
    numFailed += safeRoundTest( '0.1', 1, '0.1' );
    numFailed += safeRoundTest( '+0.1', 1, '0.1' );
    numFailed += safeRoundTest( '-0.1', 1, '-0.1' );
    numFailed += safeRoundTest( '0.9', 0, '1' );
    numFailed += safeRoundTest( '+0.9', 0, '1' );
    numFailed += safeRoundTest( '-0.9', 0, '-1' );
    numFailed += safeRoundTest( '0.9', 1, '0.9' );
    numFailed += safeRoundTest( '+0.9', 1, '0.9' );
    numFailed += safeRoundTest( '-0.9', 1, '-0.9' );
    numFailed += safeRoundTest( '0.5', 0, '1' );
    numFailed += safeRoundTest( '+0.5', 0, '1' );
    numFailed += safeRoundTest( '-0.5', 0, '-1' );
    numFailed += safeRoundTest( '0.4999', 0, '0' );
    numFailed += safeRoundTest( '+0.4999', 0, '0' );
    numFailed += safeRoundTest( '-0.4999', 0, '0' );
    numFailed += safeRoundTest( '1.005', 2, '1.01' );
    numFailed += safeRoundTest( '1.00499999999', 2, '1' );
    numFailed += safeRoundTest( '012.3456', -4, '0' );
    numFailed += safeRoundTest( '012.3456', -3, '0' );
    numFailed += safeRoundTest( '012.3456', -2, '0' );
    numFailed += safeRoundTest( '012.3456', -1, '10' );
    numFailed += safeRoundTest( '012.3456', 0, '12' );
    numFailed += safeRoundTest( '012.3456', 1, '12.3' );
    numFailed += safeRoundTest( '012.3456', 2, '12.35' );
    numFailed += safeRoundTest( '012.3456', 3, '12.346' );
    numFailed += safeRoundTest( '012.3456', 4, '12.3456' );
    numFailed += safeRoundTest( '012.3456', 5, '12.3456' );
    numFailed += safeRoundTest( '12.', 0, '12' );
    numFailed += safeRoundTest( '.12', 2, '0.12' );
    numFailed += safeRoundTest( '0e0', 0, '0' );
    numFailed += safeRoundTest( '1.2e3', 0, '1200' );
    numFailed += safeRoundTest( '1.2e+3', 0, '1200' );
    numFailed += safeRoundTest( '1.2e-3', 0, '0' );
    numFailed += safeRoundTest( '1.2e-3', 3, '0.001' );
    numFailed += safeRoundTest( '1.2e-3', 4, '0.0012' );
    numFailed += safeRoundTest( '1.2e-3', 5, '0.0012' );
    numFailed += safeRoundTest( '+12.', 0, '12' );
    numFailed += safeRoundTest( '+.12', 2, '0.12' );
    numFailed += safeRoundTest( '+0e0', 0, '0' );
    numFailed += safeRoundTest( '+1.2e3', 0, '1200' );
    numFailed += safeRoundTest( '+1.2e+3', 0, '1200' );
    numFailed += safeRoundTest( '+1.2e-3', 0, '0' );
    numFailed += safeRoundTest( '+1.2e-3', 3, '0.001' );
    numFailed += safeRoundTest( '+1.2e-3', 4, '0.0012' );
    numFailed += safeRoundTest( '+1.2e-3', 5, '0.0012' );
    numFailed += safeRoundTest( '-12.', 0, '-12' );
    numFailed += safeRoundTest( '-.12', 2, '-0.12' );
    numFailed += safeRoundTest( '-0e0', 0, '0' );
    numFailed += safeRoundTest( '-1.2e3', 0, '-1200' );
    numFailed += safeRoundTest( '-1.2e+3', 0, '-1200' );
    numFailed += safeRoundTest( '-1.2e-3', 0, '0' );
    numFailed += safeRoundTest( '-1.2e-3', 3, '-0.001' );
    numFailed += safeRoundTest( '-1.2e-3', 4, '-0.0012' );
    numFailed += safeRoundTest( '-1.2e-3', 5, '-0.0012' );
    numFailed += safeRoundTest( '9876.543e210', 0, '9.876543e+213' );
    numFailed += safeRoundTest( '9876.543e210', -210, '9.877e+213' );
    numFailed += safeRoundTest( '9876.543e210', -209, '9.8765e+213' );
    numFailed += safeRoundTest( '9876.543e+210', 0, '9.876543e+213' );
    numFailed += safeRoundTest( '9876.543e+210', -210, '9.877e+213' );
    numFailed += safeRoundTest( '9876.543e+210', -209, '9.8765e+213' );
    numFailed += safeRoundTest( '9876.543e-210', 213, '9.876543e-207' );
    numFailed += safeRoundTest( '9876.543e-210', 210, '9.877e-207' );
    numFailed += safeRoundTest( '9876.543e-210', 211, '9.8765e-207' );
    console.log( 'numFailed', numFailed );
}

safeRoundTests();

Вот модифицированная версия ответа @astorije ( /questions/181920/okruglit-do-2-znakov-posle-zapyatoj-tolko-pri-neobhodimosti/181951#181951), которая лучше поддерживает округление отрицательных значений.

      // https://stackoverflow.com/a/21323513/384884
// Modified answer from astorije
function round(value, precision) {
    // Ensure precision exists
    if (typeof precision === "undefined" || +precision === 0) {
        // Just do a regular Math.round
        return Math.round(value);
    }

    // Convert the value and precision variables both to numbers
    value = +value;
    precision = +precision;

    // Ensure the value is a number and that precision is usable
    if (isNaN(value) || !(typeof precision === "number" && precision % 1 === 0)) {
        // Return NaN
        return NaN;
    }

    // Get the sign of value
    var signValue = Math.sign(value);

    // Get the absolute value of value
    value = Math.abs(value);

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

    // Shift back
    value = value.toString().split("e");
    value = +(value[0] + "e" + (value[1] ? (+value[1] - precision) : -precision));

    // Apply the sign
    value = value * signValue;

    // Return rounded value
    return value;
}

Я нашел это работает для всех моих случаев использования:

const round = (value, decimalPlaces = 0) => {
    const multiplier = Math.pow(10, decimalPlaces);
    return Math.round(value * multiplier + Number.EPSILON) / multiplier;
};

Имейте в виду, что это ES6. ES5 эквив. было бы очень легко закодировать, поэтому я не собираюсь его добавлять.

В среде узла я просто использую модуль roundTo:

const roundTo = require('round-to');
...
roundTo(123.4567, 2);

// 123.46
number=(parseInt((number +0.005)*100))/100;     

добавить 0,005, если вы хотите, чтобы нормальный раунд (2 десятичных знака)

8.123 +0.005=> 8.128*100=>812/100=>8.12   

8.126 +0.005=> 8.131*100=>813/100=>8.13   

const formattedNumber = Math.round(число * 100) / 100;

Используя решение Брайана Устаса:

function roundDecimal(value, precision) {
    var multiplier = Math.pow(10, precision);
    return Math.round(value * multiplier) / multiplier;
}

Node.js

Это помогло мне с Node.js за считанные секунды:

npm install math

Источник: http://mathjs.org/examples/basic_usage.js.html

Здесь я использовал тернарный оператор, чтобы проверить, имеет ли число дробные значения. Если это не так, я просто возвращаю номер.

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

Intl.NumberFormatявляется частью Спецификации API интернационализации ECMAScript (ECMA402). У него довольно неплохая поддержка браузеров , включая даже IE11, и он полностью поддерживается в Node.js.

      lets say precision 2;

var num1 = 1.24167;
var num2 = 1.25678;

var numString = num1.toString();
var array = numString.split('.');
var result = array[0] + '.' + array[1].substring(0,2);
console.write( parseFloat(result) );

Я создал эту функцию для округления числа. Значение может быть строкой (например, "1.005") или числом 1.005, которое по умолчанию будет равно 1, и если вы укажете десятичное число равным 2, результатом будет 1.01.

round(value: string | number, decimals: number | string = "0"): number | null {
    return +( Math.round(Number(value + "e+"+decimals)) + "e-" + decimals);
}

Использование: round(1.005, 2) // 1.01 или Использование: round('1.005', 2) //1.01

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