43

Вопрос по javascript – Javascript toFixed Not Rounding

Я использую JavaScript для привязки к некоторым флажкам, иtoFixed(2) не округляет. Есть идеи, почему он не округляется? Например, если номер859.385 это только отображение859.38 вместо859.39.

Я также читал, чтоtoFixed Можно ли по-разному округлять в зависимости от того, какой браузер вы используете, кто-нибудь знает способ обойти это так, чтобы мои вычисления JavaScript соответствовали моим вычислениям PHP?

var standardprice = parseFloat($('#hsprice_'+this.id.split('_')[1]).val());
var price =  parseFloat($('#hprice_'+this.id.split('_')[1]).val());
var discount =  parseFloat($('#hdiscount_'+this.id.split('_')[1]).val());
var deposit =  parseFloat($('#hdeposit_'+this.id.split('_')[1]).val());

var currSprice = parseFloat($('#hTotalSprice').val());
var currPrice = parseFloat($('#hTotalPrice').val());
var currDiscount = parseFloat($('#hTotalDiscount').val());
var currDeposit = parseFloat($('#hTotalDeposit').val());

currSprice += standardprice;
currPrice += price;
currDiscount += discount;
currDeposit += deposit;

$('#lblTotalSprice').text('$'+addCommas(currSprice.toFixed(2)));
$('#lblTotalPrice').text('$'+addCommas(currPrice.toFixed(2)));
$('#lblTotalDiscount').text('$'+addCommas(currDiscount.toFixed(2)));
$('#lblTotalDeposit').text('$'+addCommas(currDeposit.toFixed(2)));

$('#hTotalSprice').val(currSprice.toFixed(2));
$('#hTotalPrice').val(currPrice.toFixed(2));
$('#hTotalDiscount').val(currDiscount.toFixed(2));
$('#hTotalDeposit').val(currDeposit.toFixed(2));
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded35.855.

    от
  • Error: User Rate Limit ExceededtoFixed10(89.684449, 2)Error: User Rate Limit Exceeded89.69Error: User Rate Limit Exceeded89.68.

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit ExceededexplanationError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit ExceededexplanationError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceededthis answerError: User Rate Limit Exceeded

    от
  • toFixed(859.3844, 2)Error: User Rate Limit Exceeded859.39Error: User Rate Limit Exceeded859.38

    от
  • Error: User Rate Limit Exceeded100 Math.pow(10, decimalpoint)Error: User Rate Limit ExceededdecimalpointError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded35.855Error: User Rate Limit Exceeded35.85Error: User Rate Limit Exceeded35.86).

    от
  • Error: User Rate Limit Exceeded100 Math.pow(10, decimalpoint)Error: User Rate Limit ExceededdecimalpointError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceededjsfiddle.net/cCX5y/3

    от
  • toFixed(859.3844, 2)Error: User Rate Limit Exceeded859.39Error: User Rate Limit Exceeded859.38

    от
  • Error: User Rate Limit Exceeded35.855Error: User Rate Limit Exceeded35.85Error: User Rate Limit Exceeded35.86).

    от
  • Error: User Rate Limit ExceededtoFixed(89.684449, 2)Error: User Rate Limit Exceeded89.69Error: User Rate Limit Exceeded89.68.

    от
  • Error: User Rate Limit Exceededthis answerError: User Rate Limit Exceeded.toFixed()

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit ExceededroundTo(89.684449, 2)Error: User Rate Limit Exceeded89.69Error: User Rate Limit Exceeded89.68.

    от
  • Error: User Rate Limit ExceedednormallyError: User Rate Limit Exceededin this answerError: User Rate Limit Exceeded(Math.round( 35.855 * 100 ) / 100).toFixed(2) == 35.85Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • var n = 1.005; console.log(n.round(2))Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit ExceededtoFixed10()Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceededjsfiddle.net/cCX5y/3

    от
  • Error: User Rate Limit Exceededen.wikipedia.org/wiki/Rounding#Double_roundingError: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceededthis answerError: User Rate Limit Exceeded.toFixed()

    от
  • Error: User Rate Limit ExceededtoFixed10()Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded35.855.

    от
  • var n = 1.005; console.log(n.round(2))Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Error: User Rate Limit Exceeded

    от
  • Вот подсказка о том, почему округление.toFixed может показаться не интуитивным(0.1).toFixed(20) , (Обратите внимание, что реализация IE дает «интуитивно понятный» результат, в то время как другие браузеры дают значение, соответствующее стандартам.)

    от Noyo
  • Мой ответ на аналогичный вопрос здесь:stackoverflow.com/a/37751946/2261514

    от Pawel
  • Поскольку 0.5 находится на полпути между 0 и 1, а округление - это всего лишь соглашение, мне интересно, насколько важно действительно гарантировать конкретный результат. С другой стороны, для тестирования вашего кода вам нужны предсказуемые результаты, и тестирование важно, так что это веская причина.

    от David Winiecki
16 ответов
  • 6

    86 */

    function roundup(num,dec){
        dec= dec || 0;
        var  s=String(num);
        if(num%1)s= s.replace(/5$/, '6');
        return Number((+s).toFixed(dec));
     }
    
     var n= 35.855
     roundup(n,2)
    

    /* returned value: (Number) 35.

  • 0

    это может помочь

        tofix2Decimals=function(float){
            if(parseInt(float)==float)return float.toFixed(2);
            $decimals=/\.(\d+)/.exec(float)[1].length;
            $decimals=$decimals>=2?$decimals+1:3;
            float+=Math.pow(10,-$decimals);
            return float.toFixed(2);
        }
    

  • 14

    Я сделал это

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

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

  • -1

    МДМ имеет

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

  • 2

    Я столкнулся с этой же проблемой сегодня

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

    function toFixed(number, fractionSize) {
        return +(Math.round(+(number.toString() + 'e' + fractionSize)).toString() + 'e' + -fractionSize);
    }
    

    Нашел здесь:Источник AngularJS filters.js

  • 0

    Это происходит из-за представления с плавающей точкой в JavaScript.

    Попробуй это:

    Number.prototype.round = function(digits) {
        digits = Math.floor(digits);
        if (isNaN(digits) || digits === 0) {
            return Math.round(this);
        }
        if (digits < 0 || digits > 16) {
            throw 'RangeError: Number.round() digits argument must be between 0 and 16';
        }
        var multiplicator = Math.pow(10, digits);
        return Math.round(this * multiplicator) / multiplicator;
    }
    
    Number.prototype.fixed = function(digits) {
        digits = Math.floor(digits);
        if (isNaN(digits) || digits === 0) {
            return Math.round(this).toString();
        }
        var parts = this.round(digits).toString().split('.');
        var fraction = parts.length === 1 ? '' : parts[1];
        if (digits > fraction.length) {
            fraction += new Array(digits - fraction.length + 1).join('0');
        }
        return parts[0] + '.' + fraction;
    }
    

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

    var n = 859.385;
    console.log(n.round(2)); // 859.39
    console.log(n.fixed(2)); // 859.39
    console.log(n.round(4)); // 859.385
    console.log(n.fixed(4)); // 859.3850
    

  • 0

    Joy twindle answer здесь должен быть лучшим ответом вместо множества в

    зломов.

       x = 1859.385;
       x = x.toFixed(2);
       alert(x);
    

    дает неправильное округление, т.е. 1859,38 вместо 1859,39

     x = 1859.385;
     x = x.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
     alert(x);
    

    дает правильное округление 1 859,39

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

     x = 1859.385;
     x = x.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2});
     x=x.replace(/\,/g,'');
     alert(x);
    

    теперь он возвращает 1859,39 и может быть использован для расчетов. Значение перед регулярным выражением, т.е. 1859,39, можно использовать для отображения html, в то время как неформатированное значение 1859,39 можно использовать для расчетов.

  • 8

    Еще одно хорошее число

    которое можно попробовать вместе с 35.855 - 1.005

    Я не думаю, что решение Роберта Мессерле обрабатывает 1.005

    Пример округления десятичной дроби здесьhttps://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round$ revision / 1383484 # Decimal_rounding преобразует числа в экспоненциальную запись и, похоже, дает лучшие результаты.

    Я создал скрипку здесьhttp://jsfiddle.net/cCX5y/2/ что демонстрирует туземец, пример Роберта Мессерла выше (называетсяtoFixedB) и один из документов Mozilla (называетсяtoFixed10).

    Я еще не нашел номер, который toFixed10 делает неправильно. Кто-нибудь еще может?

  • 5

    Так как в javascripts &

    apos; toFixed-функция, число с плавающей точкой5 не принадлежит верхней половине целого числа, данное число округляется в меньшую сторону, если у вас есть такие числа:

    859.385.toFixed(2) // results in 859.38

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

    859.3851.toFixed(2) // results in 859.39

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

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

        // both parameters can be string or number
        function toFixed(number, decimals) {
            var x = Math.pow(10, Number(decimals) + 1);
            return (Number(number) + (1 / x)).toFixed(decimals)
        }
        toFixed(859.385, 2) //results in 859.39
    

  • 14

    В Chrome 859.385 ==> 859.38 859.386 ==> 859.39

    В ChrometoFixed() Количество раундов:

    859.385 ==> 859.38
    859.386 ==> 859.39
    

    Когда я смотрю наспецификация ECMAScript 5-го издания для.toFixed() (раздел 15.7.4.5), я не вижу, чтобы он явно описывал округление, хотя он описывает довольно тупо что-то, что может быть реализовано в Chrome.

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

    var roundedNum = (Math.round( num * 100 ) / 100).toFixed(2);
    

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

    Рабочая демоверсия здесь:http://jsfiddle.net/jfriend00/kvpgE/

  • 0

    Я знаю

    что это старый вопрос, но почему бы не сделать что-то вроде этого:

    let TruncatedValueInString = ThenNumberYouWantToTruncate.toFixed(decPlaces + 1).slice(0, -1);
    

  • 1

    Я наткнулся на это удивление, почему

    Number.toFixed вел себя странно. Я вижу, что нативная функция ненадежна, что вызывает сожаление. Просматривая ответы из любопытства, я вижу, что большинство из них не ведут себя правильно с числом35.855 как T.J. Краудер любезно прокомментировал каждый.

    Может быть, это ответит на ваш вопрос.

    function toFixed(n,precision) {
        var match=RegExp("(\\d+\\.\\d{1,"+precision+"})(\\d)?").exec(n);
        if(match===null||match[2]===undefined) {
            return n.toFixed(precision);
            }
        if(match[2]>=5) {
            return (Number(match[1])+Math.pow(10,-precision)).toFixed(precision);
            }
        return match[1];
        }
    

    Регулярное выражение разбивает ваш номер на массив строк, таких как вtoFixed(35.855,2): ["35.855", "35.85", "5"], Если последнее число (после точности отсечки)>=5, добавлятьMath.pow(10, -precision) на обрезанный номер. Это добавит.01 если вы отрежете с точностью до 2 десятичных знаков,.002 на 3 и так далее.

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

  • 0

    toFixed () работает правильно!

    Проблема в том, что 859.385 не имеет представления как float на компьютере. Это сканируется как ближайшее возможное значение = 859,384999999999991. И округление этого значения до 2 цифр составляет 859,38, а не 859,39.

    Это причина того, что многие (особенно старые для торговли, например, COBOL) языки программирования поддерживают числа BCD (двоично-десятичные десятичные числа), где каждая цифра кодируется сама по себе в 4 бита (как шестнадцатеричный код без использования A-F).

    Общее решение по ценам: - Рассчитайте в центах / копейках и напечатайте НОМЕР / 100.

    Примечание к другим решениям (функции представлены здесь): Они могут помочь для некоторых чисел, но в основном терпят неудачу, например. +859,38499999.

  • 28

    I have yet to find a number that toFixed10 does wrong. Can anybody els

    e?

    Благодаряblg а такжеего ответ который указал мне на MozillatoFixed10 () метод.

    Используя это, я придумал этот короткий вкладыш, который действительно охватывает все случаи, упомянутые здесь ...

    function toFixed( num, precision ) {
        return (+(Math.round(+(num + 'e' + precision)) + 'e' + -precision)).toFixed(precision);
    }
    

  • 2

    Если вы ищете, чтобы получить

    a number as outputзатем рассмотримMath.round() техника в других ответах.

    Но если вы хотите получитьa string as output, for presentation to a humanпотом частоn.toLocaleString() является более полезным, чемn.toFixed().

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

    var n = 1859.385
    
    n.toLocaleString(undefined, {minimumFractionDigits: 2, maximumFractionDigits: 2})
    
    // Produces  1,859.39  in USA (locale en-US)
    // Produces  1 859,39  in France (locale fr-FR)
    // Produces  1.859,39  in Germany (locale de-DE)
    

    В спецификации сказано, что при прохожденииundefined в качестве первого аргумента будет использоваться собственный языковой стандарт пользователя (как указано в ОС). К сожалению, как показывает связанная документация, Mozilla использует локализацию en-US в этой ситуации, но в будущем она может соответствовать спецификации.

  • 3

    Вы можете использовать var result=Math.round(original*100)/100

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

    var result=Math.round(original*100)/100