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

2106

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

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

10
1.7777777
9.1

Вывод:

10
1.78
9.1

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

  • 14
    Я сделал скрипку со многими из техник, предложенных здесь как решения ... так что вы можете сравнить: fiddle
  • 16
    Кажется, никто не знает о Number.EPSILON . Используйте Math.round( num * 100 + Number.EPSILON ) / 100 .
Показать ещё 2 комментария
Теги:
decimal
rounding
decimal-point

62 ответа

2410
Лучший ответ

Используйте Math.round(num * 100) / 100

  • 321
    Хотя это будет работать в большинстве случаев, оно не будет работать для 1.005, который в итоге окажется 1 вместо 1.01
  • 66
    @ Джеймс Вау, это действительно странно - я работаю в консоли разработчика Chrome и замечаю, что 1.005 * 100 = 100.49999999999999. Math.round (100.49999999999999) оценивается до 100, тогда как Math.round (100.5) оценивается до 101. IE9 делает то же самое. Это из-за странности с плавающей точкой в JavaScript
Показать ещё 31 комментарий
2596

Если значение представляет собой текстовый тип:

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 на самом деле что-то вроде float 1.55499994 за кулисами.

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

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 состоит в том, чтобы избежать вычислений переднего конца и вытащить округленные значения с серверного сервера.

  • 73
    Этот подход (toFixed) хорош и работает для меня, но он, в частности, не соответствует первоначальному запросу «только при необходимости». (Округляет 1,5 до 1,50, что нарушает спецификацию.)
  • 24
    Для требования «когда необходимо» сделайте это: parseFloat(number.toFixed(decimalPlaces)); @PerLundberg
Показать ещё 29 комментариев
371

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

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
  • 11
    @Redsandro, +(val) - эквивалент приведения Number(val) . Конкатенация «e-2» с числом привела к появлению строки, которую необходимо преобразовать обратно в число.
  • 35
    Имейте в виду, что для больших и маленьких поплавков, которые будут производить NaN, например, + "1e-21 + 2" не будут анализироваться правильно.
Показать ещё 13 комментариев
117

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

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

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

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

Unit test:

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');
  });
})
  • 18
    Пьер поднял серьезную проблему с ответом MarkG.
  • 7
    Примечание. Если вы не хотите изменять прототип Number.pro - просто напишите его как функцию: function round(number, decimals) { return +(Math.round(number + "e+" + decimals) + "e-" + decimals); }
Показать ещё 5 комментариев
72

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

var str = 10.234.toFixed(2); // => '10.23'
var number = Number(str); // => 10.23
  • 0
    Почему это не лучший ответ ??? (РЕДАКТИРОВАТЬ: о, потому что он преобразуется в строку :)
  • 4
    Кроме того, потому что это добавляет завершающие нули, что не то, что просили оригинальный вопрос .
Показать ещё 4 комментария
60

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

Предположим, что у нас есть функция roundTo2DP(num), которая принимает float как аргумент и возвращает значение, округленное до 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 в String...

> 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 -1 ≤ s < 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,0149999999999999999944488848768742172978818416595458984375, но его строковое представление "0,015", тогда какой правильный ответ - математически, практически, философски или что-то еще - когда мы округлим его до двух знаков после запятой?

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

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

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

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

/**
 * 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://stackoverflow.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, которая обеспечивает аналогичную работу с совершенно другой реализацией).

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

Здесь мы можем просто использовать встроенный метод toFixed. Обратите внимание, что, вызывая Number() в String, возвращаемом toFixed, мы получаем Number, представление String которого не имеет конечных нулей (благодаря тому, как 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://stackoverflow.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);
}
/**
 * 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://stackoverflow.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);
}
  • 0
    Это не работает в некоторых крайних случаях: try ( jsfiddle ) с roundStringNumberWithoutTrailingZeroes(362.42499999999995, 2) . Ожидаемый результат (как в echo round(362.42499999999995, 2) PHP echo round(362.42499999999995, 2) ): 362.43 . Фактический результат: 362.42
  • 1
    @ Dr.GianluigiZaneZanettini Да. Weird. Я не уверен, почему round PHP дает 362,43. Это кажется интуитивно неправильным, поскольку 362.42499999999995 меньше 362,425 (в математике и в коде - 362.42499999999995 < 362.425 верно как для JS, так и для PHP). Ответ PHP также не минимизирует расстояние между исходным и округленным числами с плавающей запятой, поскольку 362.43 - 362.42499999999995 > 362.42499999999995 - 362.42 . Согласно php.net/manual/en/function.round.php , round PHP соответствует стандарту C99; Я должен рискнуть в страну Си, чтобы понять, что происходит.
Показать ещё 4 комментария
57

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

(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
  • 0
    Кто-то также поместил это на GitHub и npm: github.com/jhohlfeld/round10
  • 0
    Нет, Math.round10(3544.5249, -2) возвращает 3544,52 вместо 3544,53
Показать ещё 3 комментария
54

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

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

Math.ceil(num * 100)/100;
  • 14
    Пример ввода и вывода показывает, что, хотя в вопросе говорилось «округлить вверх ...», на самом деле он был задуман как «округлить до ...».
  • 2
    @stinkycheeseman указывал на ошибку в конкретном случае, он не хотел всегда округлять, как это делает ceil, он просто хотел, чтобы 0,005 округлилось до 0,01.
Показать ещё 7 комментариев
51

Рассмотрим .toFixed() и .toPrecision():

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

  • 0
    toFixed добавляет десятичные точки к каждому значению, несмотря ни на что.
  • 7
    Оба здесь бесполезны
Показать ещё 4 комментария
42

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

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 имеет значение только тогда, когда значение round равно результатом арифметической операции, так как оно может усвоить некоторую ошибку Number.EPSILON плавающей запятой.

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

  • 0
    Number.EPSILON не определено в Internet Explorer.
  • 1
    @palota, вы можете определить действительно число зубьев, как упоминается в названии EPSILON.
Показать ещё 12 комментариев
42

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

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);
}
  • 0
    Это должен быть самый голосующий ответ.
  • 2
    Это решение является неправильным, см stackoverflow.com/questions/38322372/... , если вы вводите 156893,145 и вокруг него с вышеописанной функции вы получаете 156893.14 вместо 156893.15 !!!
Показать ещё 1 комментарий
35
+(10).toFixed(2); // = 10
+(10.12345).toFixed(2); // = 10.12

(10).toFixed(2); // = 10.00
(10.12345).toFixed(2); // = 10.12
  • 1
    Это не всегда даст те же результаты, которые вы получили бы, если бы вы взяли строковое представление вашего числа и округлили его. Например, +(0.015).toFixed(2) == 0.01 .
34

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

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

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

number = 1; // "1"
number.toFixed(5).replace(/\.?0*$/g,'');
  • 3
    Метод toFixed возвращает строку. Если вы хотите получить числовой результат, вам нужно отправить результат toFixed в parseFloat.
  • 0
    @Zambonilli Или просто умножьте на 1, если это необходимо. но, поскольку фиксированное число в большинстве случаев предназначено для отображения, а не для вычисления строки, это правильный формат
Показать ещё 4 комментария
32

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

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

console.log(((43000 / 80000) * 100).toFixed(2)); // correct answer
  • 0
    Важно отметить, что toFixed не выполняет округление, а Math.round просто округляет до ближайшего целого числа. Поэтому, чтобы сохранить десятичные дроби, нам нужно умножить исходное число на количество степеней десяти, нули которых представляют желаемое количество десятичных знаков, а затем разделить результат на то же число. В вашем случае: Math.round (43000/80000 * 100 * 100) / 100. Наконец, toFixed (2) может быть применен для обеспечения того, чтобы в результате всегда было два знака после запятой (с конечными нулями, где это необходимо) - идеально для выравнивания правого ряда чисел, представленных вертикально :)
  • 6
    Также важно отметить, что .toFIxed () выводит строку, а не число.
Показать ещё 1 комментарий
30

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

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

 round(1.222,  2) ;
 // 1.22
 round(1.222, 10) ;
 // 1.222
  • 4
    Намного аккуратнее, по крайней мере для меня, чем принятый ответ. Спасибо!
  • 0
    Кто-нибудь знает, есть ли разница между этим и return Number(x.toFixed(digits)) ?
Показать ещё 3 комментария
28

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

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

  • 0
    Второй вариант вернет строку с двумя точками после запятой. Вопрос требует десятичных знаков только в случае необходимости. Первый вариант лучше в этом случае.
  • 0
    @MarcosLima Number.toFixed() вернет строку, но с символом плюс перед ней, интерпретатор JS преобразует строку в число. Это синтаксис сахара.
Показать ещё 5 комментариев
21

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
  • 2
    Ваше решение не распространяется на некоторые случаи, в отличие от решения MDN. Хотя это может быть короче, это не точно ...
  • 1
    круглый (-1835,665,2) => -1835,66
17

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

_.round(number, precision)

Например:

_.round(1.7777777, 2) = 1.78
  • 0
    lodash должен быть стандартной библиотекой JavaScript
  • 0
    @Peter Набор функций, которые предоставляет Lodash, действительно хорош по сравнению со стандартным Javascript. Однако я слышал, что у Lodash есть некоторые проблемы с производительностью по сравнению со стандартным JS. codeburst.io/...
Показать ещё 1 комментарий
16
var roundUpto = function(number, upto){
    return Number(number.toFixed(upto));
}
roundUpto(0.1464676, 2);

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

  • 0
    это .toFixed () проще в реализации. просто пройди через это один раз.
  • 0
    большое спасибо, очень простой ответ
14

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

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

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

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

12

Используйте что-то вроде этого "parseFloat (parseFloat (значение).toFixed(2))"

parseFloat(parseFloat("1.7777777").toFixed(2))-->1.78 
parseFloat(parseFloat("10").toFixed(2))-->10 
parseFloat(parseFloat("9.1").toFixed(2))-->9.1
  • 0
    это единственный правильный ответ на этой странице.
  • 0
    нет, если неточность присуща представлению с плавающей точкой. Вы просто удалили бы его, а затем снова повторили ту же ошибку, снова преобразовав ее в float!
12

Самый простой способ:

+num.toFixed(2)

Он преобразует его в строку, а затем обратно в целое число/float.

  • 0
    Спасибо за этот самый простой ответ. Однако что такое «+» в + num? Это не сработало для меня, когда десятичный вал пришел в строке. Я сделал: (num * 1). ToFixed (2).
  • 1
    Это не распространяется на 1.005, @See stackoverflow.com/a/29924251/961018
Показать ещё 2 комментария
11

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

Использование экспоненциальной нотации позволяет правильно округлить число +ve. Тем не менее, этот метод не позволяет правильно обработать края -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
  • 0
    Работает как шарм :)
11

Вот прототип метода:

Number.prototype.round = function(places){
    places = Math.pow(10, places); 
    return Math.round(this * places)/places;
}

var yournum = 10.55555;
yournum = yournum.round(2);
10

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

Math.round(num * 100)/100;

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

9

Если вы уже используете библиотеку d3, у них есть мощная библиотека форматирования чисел: https://github.com/mbostock/d3/wiki/Formatting

Округление конкретно здесь: https://github.com/mbostock/d3/wiki/Formatting#d3_round

В вашем случае ответ:

> d3.round(1.777777, 2)
1.78
> d3.round(1.7, 2)
1.7
> d3.round(1, 2)
1
  • 2
    Глядя на источник , это не более чем обобщенная версия ответа @ustasb, использующая num * Math.pow(n) вместо num * 100 (но это определенно аккуратный однострочный ;-)
  • 0
    Но задокументировано, и, находясь в библиотеке, мне больше не нужно проверять совместимость браузера с BS.
Показать ещё 1 комментарий
9

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

Math.round(num * 1e2) / 1e2
8

Поскольку 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));
  • 0
    (1.005).toPrecision(3) прежнему возвращает 1.00 вместо 1.01 самом деле.
  • 0
    toPrecision возвращает строку, которая изменяет желаемый тип вывода.
Показать ещё 1 комментарий
8

Более простой способ ES6 - это

const round = (x, n) => 
  parseFloat(Math.round(x * Math.pow(10, n)) / Math.pow(10, n)).toFixed(n);

Этот шаблон также возвращает заданную точность.

например:

round(44.7826456, 4)  // yields 44.7826
round(78.12, 4)       // yields 78.1200
8

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

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

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

  • 0
    На сегодняшний день это самое чистое решение, которое обходит все сложные проблемы с плавающей запятой, но поддержка для каждого MDN все еще не завершена - Safari пока не поддерживает передачу аргументов в toLocaleString .
7

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

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
  • 4
    Это хороший способ переписать принятый ответ, чтобы принять аргумент, используя обозначение E
  • 0
    не в моем MacBook Pro вижу, что
Показать ещё 3 комментария
7

Я добавлю еще один подход к этому.

number = 16.6666666;
console.log(parseFloat(number.toFixed(2)));
"16.67"

number = 16.6;
console.log(parseFloat(number.toFixed(2)));
"16.6"

number = 16;
console.log(parseFloat(number.toFixed(2)));
"16"

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

7

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

  • 7
    Оберните все это в Number раз, если вы не хотите, чтобы оно возвращалось в виде строки: Number(Number(x).toFixed(2));
  • 3
    Вызов Number не требуется, x.toFixed(2) работает.
Показать ещё 1 комментарий
5

Простое решение будет использовать функцию lodash ceil, если вы хотите округлить...

https://lodash.com/docs/4.17.10#ceil

_.round(6.001,2)

дает 6

_.ceil(6.001, 2);

дает 6,01

_.ceil(37.4929,2);

дает 37,5

_.round(37.4929,2);

дает 37,49

  • 2
    Нет смысла импортировать новую зависимость, просто делать округления.
  • 0
    Очень забавно, что вы еще не используете lodash в своем проекте javascript, учитывая, какие функции предоставляет lodash ...
Показать ещё 1 комментарий
4

Это помогло (TypeScript):

round(decimal: number, decimalPoints: number): number{
    let roundedValue = Math.round(decimal * Math.pow(10, decimalPoints)) / Math.pow(10, decimalPoints);

    console.log('Rounded ${decimal} to ${roundedValue}');
    return roundedValue;
}

// Sample output:
Rounded 18.339840000000436 to 18.34
Rounded 52.48283999999984 to 52.48
Rounded 57.24612000000036 to 57.25
Rounded 23.068320000000142 to 23.07
Rounded 7.792980000000398 to 7.79
Rounded 31.54157999999981 to 31.54
Rounded 36.79686000000004 to 36.8
Rounded 34.723080000000124 to 34.72
Rounded 8.4375 to 8.44
Rounded 15.666960000000074 to 15.67
Rounded 29.531279999999924 to 29.53
Rounded 8.277420000000006 to 8.28
4

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

Самое простое и кратчайшее решение без каких-либо побочных эффектов:

Number((2.3456789).toFixed(2)) // 2.35

Он округляется правильно и возвращает число вместо строки

console.log(Number((2.345).toFixed(2)))  // 2.35
console.log(Number((2.344).toFixed(2)))  // 2.34
console.log(Number((2).toFixed(2)))      // 2
console.log(Number((-2).toFixed(2)))     // -2
console.log(Number((-2.345).toFixed(2))) // -2.35

console.log(Number((2.345678).toFixed(3))) // 2.346
  • 2
    console.log (Number ((1.005) .toFixed (2))) по-прежнему выдает «1,00» вместо «1,01»
4

Попробуйте использовать плагин jQuery .:

var number = 19.8000000007;
var res = 1 * $.number(number, 2);
3

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

если вы хотите создать округленное десятичное число, сначала вы вызываете toFixed(# of decimal places you want to keep) а затем обертываете это в Number()

поэтому конечный результат:

let amountDue = 286.44;
tip = Number((amountDue * 0.2).toFixed(2));
console.log(tip)  // 57.29 instead of 57.288
  • 0
    Это не отвечает на вопрос, который был о округлении и возвращении числа. toFixed просто toFixed значение и возвращает строку. Number(1.005).toFixed(2) => "1.00"
  • 0
    И это решение также не идет с «только при необходимости» частью вопроса: Number(10).toFixed(2) => "10.00"
3

Для округления в десятичных положениях pos (включая десятичные знаки) do Math.round(num * Math.pow(10,pos)) / Math.pow(10,pos)

var console = {
 log: function(s) {
  document.getElementById("console").innerHTML += s + "<br/>"
 }
}
var roundDecimals=function(num,pos) {
 return (Math.round(num * Math.pow(10,pos)) / Math.pow(10,pos) );
}
//https://en.wikipedia.org/wiki/Pi
var pi=3.14159265358979323846264338327950288419716939937510;
for(var i=2;i<15;i++) console.log("pi="+roundDecimals(pi,i));
for(var i=15;i>=0;--i) console.log("pi="+roundDecimals(pi,i));
<div id="console" />
3

Вот кратчайший и полный ответ:

function round(num, decimals) {
        var n = Math.pow(10, decimals);
        return Math.round( (n * num).toFixed(decimals) )  / n;
};

Это также касается примера 1.005, который вернет 1.01.

  • 1
    Все еще терпит неудачу для некоторого числа. Попробуйте раунд (1234.00000254495, 10), где он вернется 1234.0000025449. Метод Mozilla, который вы правильно прокомментировали, правильно округляет это значение.
  • 0
    @LostInComputer (10.00000254495) .toFixed (10) возвращает «10.0000025450», (100.00000254495) .toFixed (10) возвращает «100.0000025449», и угадайте, что (100.00000254495) .toFixed (10) вернет? Да: "1000.0000025450". Таким образом, проблема больше других причин, чем этот метод. Попробуйте это: console.log (1234578.9012345689) ... Если вы переместите точку вправо, то число будет расти, и вы не получите столько десятичных дробей. Вы не можете получить более 18 номеров (в этом примере). Затем попробуйте это: console.log (123455.00000254495), он выведет 123455.00000254496. Вот как браузеры обрабатывают числа.
Показать ещё 1 комментарий
3

Вы также можете переопределить функцию Math.round для правильного округления и добавить параметр для десятичных знаков и использовать его так: Math.round(Number, Decimals). Имейте в виду, что это переопределяет встроенный компонент Math.round и дает ему другое свойство, тогда оно оригинальное.

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

Тогда вы можете просто использовать его следующим образом:

Math.round(1.005, 2);

https://jsfiddle.net/k5tpq3pd/3/

3

Я написал для себя следующий набор функций. Возможно, это тоже поможет.

function float_exponent(number) {
    exponent = 1;
    while (number < 1.0) {
        exponent += 1
        number *= 10
    }
    return exponent;
}
function format_float(number, extra_precision) {
    precision = float_exponent(number) + (extra_precision || 0)
    return number.toFixed(precision).split(/\.?0+$/)[0]
}

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

format_float(1.01); // 1
format_float(1.06); // 1.1
format_float(0.126); // 0.13
format_float(0.000189); // 0.00019

Для вас:

format_float(10, 1); // 10
format_float(9.1, 1); // 9.1
format_float(1.77777, 1); // 1.78
3

Вот функция, которую я придумал, чтобы "округлить". Я использовал двойной 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);
}
  • 1
    Я проверил это снова, и он работает для меня .. (alert (myRound (1234.56789, 2)); //1234.57) Может быть, вас смущают множественные операторы return?
  • 0
    Повышение, как это, возможно, долгий способ сделать это, но это работает.
Показать ещё 1 комментарий
2

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

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

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

1

Основываясь на выбранном ответе и поднятом комментарии на тот же вопрос:

Math.round((num + 0.00001) * 100) / 100

Это работает для обоих этих примеров:

Math.round((1.005 + 0.00001) * 100) / 100

Math.round((1.0049 + 0.00001) * 100) / 100
  • 1
    Эта функция не работает на 1.004999
1

Это сработало очень хорошо для меня, когда я хотел всегда округлять до определенного десятичного числа. Ключевым моментом здесь является то, что мы всегда будем округлять с помощью функции 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))
1

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

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

// 123.46
1

Начиная с примера, предложенного над precisionRound, который я нашел на MDN (это событие для 1.005 returs 1, а не 1.01), я пишу пользовательскую точность Round, которая управляет номером случайной точности и для 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);
}
  • 0
    Я хотел бы знать, почему это было дано downvote? Кто это делает, также должен прокомментировать причину. Эта функция полезна и не входит в число тех, которые уже присутствуют в ответах.
1

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

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);
1

Только для записи метод масштабирования теоретически может вернуть Infinity, если число и цифры, которые вы хотите округлить, достаточно велики. В 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;
}
1

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

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

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>
0

Этот ответ скорее о скорости.

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 об этом.

0

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

public static roundFinancial(amount: number, decimals: number) {
    return Number(Math.round(Number('${amount}e${decimals}')) + 'e-${decimals}');
}
  • 0
    для меня это не похоже на javascript, и chrome его не принимает - VM82:1 Uncaught SyntaxError: Unexpected identifier
0

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

function roundDecimal(value, precision) {
    var multiplier = Math.pow(10, precision);
    return Math.round(value * multiplier) / multiplier;
}
0
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   
0

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

раунд (1.005, 2);//return 1.01

раунд (1.004, 2);//возвращаем 1 вместо 1.00

Ответ идет по этой ссылке: http://www.jacklmoore.com/notes/rounding-in-javascript/

0

Попробуйте выполнить эту функцию в typescript (Angular 2). Протестировано в комплексных десятичных знаках.

/**
 * @param num numeric to round off
 * @param decToRound desired decimal digit to round
 */
roundNumberDec(num, decToRound) {
    if ([undefined, null, ''].indexOf(num) >= 0) {
        return null;
    }
    if (isNaN(num)) { return null; }
    // check if decimal
    if (num.toString().indexOf('.') > -1) {
        const deci = num.toString().split('.')[1];
        if (deci.length <= decToRound) { return Number(num); }
        let isUp = false; let newDecimal = 0;
        let digi;
        for (let i = deci.length - 1; i > decToRound - 1; i--) {
            digi = Number(Number(deci.charAt(i)) + (isUp ? 1 : 0));
            isUp = digi >= 5;
        }
        const frontDigi = num.toString().substr(0, num.toString().indexOf('.'));
        const dec2dig = '0.' + deci.toString().substr(0, decToRound);
        if (isUp) {
            const rounder = Math.pow(10, decToRound);
            newDecimal = Math.round((Number(dec2dig) + (1 / rounder)) * rounder) / rounder;
        } else {
            newDecimal = Number(dec2dig);
        }
        return Number(Number(frontDigi) + Number(newDecimal));
    } else {
        return Number(num);
    }
}
0

Пожалуйста, используйте функцию ниже, если вы не хотите округлять.

function ConvertToDecimal(num) {
  num = num.toString(); // If it not already a String
  num = num.slice(0, (num.indexOf(".")) + 3); // With 3 exposing the hundredths place    
alert('M : ' + Number(num)); // If you need it back as a Number     
}
  • 0
    Вы должны иметь желаемые десятичные разряды, чтобы быть вторым параметром функции, которая «по умолчанию» составляет 2 или 3 десятичных разряда.
0

Node.js

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

npm install math

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

  • 2
    В конце концов, для простых чисел используется трюк Math.round(v*100)/100 . github.com/josdejong/mathjs/blob/master/lib/function/arithmetic/...
  • 0
    Спасибо за добавление lapo, так что ученый-компьютер захочет узнать, как это на самом деле реализовано. Тем не менее - разработчик будет доволен концепцией сокрытия информации и не нуждается в уходе.
Показать ещё 2 комментария
-1

Я попробовал свой собственный код, попробуйте

function AmountDispalyFormat(value) {
    value = value.toFixed(3);
    var amount = value.toString().split('.');
    var result = 0;
    if (amount.length > 1) {
        var secondValue = parseInt(amount[1].toString().slice(0, 2));
        if (amount[1].toString().length > 2) {
            if (parseInt(amount[1].toString().slice(2, 3)) > 4) {
                secondValue++;
                if (secondValue == 100) {
                    amount[0] = parseInt(amount[0]) + 1;
                    secondValue = 0;
                }
            }
        }

        if (secondValue.toString().length == 1) {
            secondValue = "0" + secondValue;
        }
        result = parseFloat(amount[0] + "." + secondValue);
    } else {
        result = parseFloat(amount);
    }
    return result;
}
-2

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

let numbers = 5.1356;

const countingDecimals = (numbers) => {
  let decimal = numbers.toString().split(".").length;
  return decimal;
}

if (countingDecimals(numbers) === 0) {
  let localNumbers = numbers;
  localNumbers = Math.Floor(localNumbers);
  console.log(localNumbers); 
  } else if (countingDecimals(numbers) === 1) {
  let localNumbers = numbers;
  localNumbers = Math.round(localNumbers * 10) / 10
  console.log(localNumbers); 
  } else {
  let localNumbers = numbers;
  localNumbers = Math.round(localNumbers * 100) / 100;
  console.log(localNumbers); }
-10

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

var num = 3.21;
if ( (num+"").indexOf('.') >= 0 ) { //at least assert to string first...
    // whatever code you decide to use to round
}
  • 3
    indexOf - это прежде всего не метод для чисел.
  • 2
    В вопросе спрашивалось, как округлять числа, а не просто проверять, нужно ли их округлять.

Ещё вопросы

Сообщество Overcoder
Наверх
Меню