Как отформатировать float в javascript?


В JavaScript при преобразовании из float в строку, как я могу получить всего 2 цифры после десятичной точки? Например, 0,34 вместо 0,3445434.



Answers



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

Специфика , если код не является самоочевидным.

изменить: ... или просто использовать toFixed , как было предложено Тимом Бютом . Забыл тот, спасибо (и upvote) за напоминание :)




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

var x = 5.0364342423;
print(x.toFixed(2));

напечатает 5.04.

Редактировать: Fiddle




Будьте осторожны при использовании toFixed() :

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

(0.595).toFixed(2) === '0.59'

вместо '0.6' .

Во-вторых, есть ошибка IE с toFixed() . В IE (по крайней мере, до версии 7, не проверял IE8), выполняется следующее:

(0.9).toFixed(0) === '0'

Может быть хорошей идеей следовать предложению kkyy или использовать пользовательскую toFixed() , например

function toFixed(value, precision) {
    var power = Math.pow(10, precision || 0);
    return String(Math.round(value * power) / power);
}



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

var x=(23-7.37)
x
15.629999999999999
x.toFixed(6)
"15.630000"

Идея состоит в том, чтобы очистить выход с помощью RegExp :

function humanize(x){
  return x.toFixed(6).replace(/\.?0*$/,'');
}

RegExp соответствует конечным нулям (и, необязательно, десятичной точке), чтобы убедиться, что он отлично подходит для целых чисел.

humanize(23-7.37)
"15.63"
humanize(1200)
"1200"
humanize(1200.03)
"1200.03"
humanize(3/4)
"0.75"
humanize(4/3)
"1.333333"



var x = 0.3445434
x = Math.round (x*100) / 100 // this will make nice rounding



Эта проблема, вероятно, стоит еще одного ответа: как упоминалось Dony и ArteQ, на округление влияет потеря точности (то есть 0.5 может стать 0.49999 ...). Следствием этого является то, что округление не является ни половинным , ни половинным , ни любым другим последовательным методом округления, и даст непоследовательный результат независимо от используемого вами метода.

Действительно, toFixed затронут:

(0.335).toFixed(2) == 0.34
(0.345).toFixed(2) == 0.34

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

Например, для округления вверх по полу, используя toFixed :

var epsilon = 0.001;
(0.335 + epsilon).toFixed(2) == 0.34;
(0.345 + epsilon).toFixed(2) == 0.35;

Это то же самое, если вы создаете свою собственную функцию, добавляете / удаляете epsilon перед вычислением.

Обновить :

Как указывалось матиас, у этих методов есть недостаток: какое значение эпсилона, 0.334999999 ... будет всегда округлено до 0,34 вместо 0,35. Поэтому мы имеем согласованность, но не «стандартное округление».




Существует проблема со всеми этими решениями, использующими множители. Кя, кыки и решения Кристофа, к сожалению.

Пожалуйста, проверьте свой код на номер 551.175 с 2 десятичными знаками - он будет округлен до 551,17, тогда как он должен быть 551,18 ! Но если вы проверите напр. 451.175 это будет нормально - 451.18. Поэтому на первый взгляд трудно заметить эту ошибку.

Проблема заключается в умножении: try 551.175 * 100 = 55117.49999999999 (ups!)

Поэтому моя идея - обработать его с помощью toFixed () перед использованием Math.round ();

function roundFix(number, precision)
{
    var multi = Math.pow(10, precision);
    return Math.round( (number * multi).toFixed(precision + 1) ) / multi;
}



function trimNumber(num, len) {
  const modulu_one = 1;
  const start_numbers_float=2;
  var int_part = Math.trunc(num);
  var float_part = String(num % modulu_one);
      float_part = float_part.slice(start_numbers_float, start_numbers_float+len);
  return int_part+'.'+float_part;
}



Может быть, вам также понадобится десятичный разделитель? Вот функция, которую я только что сделал:

function formatFloat(num,casasDec,sepDecimal,sepMilhar) {
    if (num < 0)
    {
        num = -num;
        sinal = -1;
    } else
        sinal = 1;
    var resposta = "";
    var part = "";
    if (num != Math.floor(num)) // decimal values present
    {
        part = Math.round((num-Math.floor(num))*Math.pow(10,casasDec)).toString(); // transforms decimal part into integer (rounded)
        while (part.length < casasDec)
            part = '0'+part;
        if (casasDec > 0)
        {
            resposta = sepDecimal+part;
            num = Math.floor(num);
        } else
            num = Math.round(num);
    } // end of decimal part
    while (num > 0) // integer part
    {
        part = (num - Math.floor(num/1000)*1000).toString(); // part = three less significant digits
        num = Math.floor(num/1000);
        if (num > 0)
            while (part.length < 3) // 123.023.123  if sepMilhar = '.'
                part = '0'+part; // 023
        resposta = part+resposta;
        if (num > 0)
            resposta = sepMilhar+resposta;
    }
    if (sinal < 0)
        resposta = '-'+resposta;
    return resposta;
}



Невозможно избежать несогласованного округления цен с x.xx5 как фактическое значение с использованием либо умножения, либо деления. Если вам нужно рассчитать правильные цены на стороне клиента, вы должны хранить все суммы в центах. Это связано с характером внутреннего представления числовых значений в JavaScript. Обратите внимание, что Excel страдает от одних и тех же проблем, поэтому большинство людей не замечают небольших ошибок, вызванных этим феноменом. Однако ошибки могут накапливаться всякий раз, когда вы добавляете много вычисленных значений, существует целая теория вокруг этого, включающая порядок вычислений и другие методы, чтобы минимизировать ошибку в конечном результате. Чтобы подчеркнуть проблемы с десятичными значениями, обратите внимание, что 0,1 + 0,2 не точно равно 0,3 в JavaScript, а 1 + 2 равно 3.




/** don't spend 5 minutes, use my code **/
function prettyFloat(x,nbDec) { 
    if (!nbDec) nbDec = 100;
    var a = Math.abs(x);
    var e = Math.floor(a);
    var d = Math.round((a-e)*nbDec); if (d == nbDec) { d=0; e++; }
    var signStr = (x<0) ? "-" : " ";
    var decStr = d.toString(); var tmp = 10; while(tmp<nbDec && d*tmp < nbDec) {decStr = "0"+decStr; tmp*=10;}
    var eStr = e.toString();
    return signStr+eStr+"."+decStr;
}

prettyFloat(0);      //  "0.00"
prettyFloat(-1);     // "-1.00"
prettyFloat(-0.999); // "-1.00"
prettyFloat(0.5);    //  "0.50"



    You can try this if you want don't want rounding
`function myFunction() {
        var str = 12.234556; 
        str = str.toString().split('.');
        var res = str[1].slice(0, 2);
        document.getElementById("demo").innerHTML = str[0]+'.'+res;
    }`
output:12.23