Як відформатувати float у javascript?


427

Як в JavaScript при перетворенні з поплавця на рядок, як я можу отримати лише 2 цифри після десяткової точки? Наприклад, 0,34 замість 0,3445434.


16
Лише декілька наборів азоту: ви хочете "відрізати" всі, крім двох перших цифр, або ви хочете округлити до двох цифр?
xtofl

Відповіді:


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

Особливості , якщо код не пояснює себе.

редагувати: ... або просто використовувати toFixed, як запропонував Тім Бют . Забув це, спасибі (та нагороду) за нагадування :)


1
Я використовував це в бібліотеці "Highchart", де він не приймає значення рядків, отже, toFixed не працював для мене, Math.round вирішив мою проблему, дякую
Swapnil Chincholkar

4
toFixed()буде імітувати те, що щось подібне printf()робить у C. Однак, toFixed()і Math.round()буде обробляти округлення по-різному. У цьому випадку toFixed()матиме такий самий ефект, як і у Math.floor()випадку (якщо ви попередньо помножили оригінал на 10 ^ n і подзвоните toFixed()з n цифр). "Правильність" відповіді дуже залежить від того, чого хоче тут ОП, і обидва по-своєму "правильні".
DDPWNAGE

838

Існують функції для округлення чисел. Наприклад:

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

буде надруковано 5.04.

EDIT: Fiddle


7
Я б рекомендував не використовувати print () у веб-переглядачі
cobbal

70
Будьте уважні з цього приводу, toFixed () повертає рядок: var x = 5.036432346; var y = x.toFixed(2) + 100; yбуде рівним"5.03100"
Влад

5
Будьте в курсі, що (1e100) .toFixed (2) === "1e + 100"
qbolec

7
Також остерігайтеся непослідовного округлення: (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)
Skippy le Grand Gourou

3
Якщо ви шукаєте еквівалент toFixed, але з послідовним округленням, використовуйте toLocaleString: (0.345) .toLocaleString ('en-EN', {minimumFractionDigits: 2, максимальнийFractionDigits: 2})
fred727

185

Будьте уважні при використанні 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);
}

Так, це може бути дуже важливим при створенні коду для прогнозування цін. Дякую! +1
Фабіо Мілхейро

10
Я б запропонував додати початковий .toFixed()метод у повернене значення, що додасть необхідну точність, наприклад: return (Math.round(value * power) / power).toFixed(precision);а також поверне значення у вигляді рядка. Інакше точність 20 ігнорується для менших десяткових знаків
Вільям Джосс Кроукрофт

3
Одне зауваження щодо toFixed: зауважте, що підвищення точності може дати неочікувані результати:, в (1.2).toFixed(16) === "1.2000000000000000"той час, як (1.2).toFixed(17) === "1.19999999999999996"(у Firefox / Chrome; в IE8 останній не виконується через меншу точність, яку IE8 може запропонувати всередині).
jakub.g

2
Зверніть увагу, що навіть (0.598).toFixed(2)це не дає 0.6. Це виробляє 0.60:)
qbolec

1
Крім того , остерігайтеся inconstistent округлення: (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2).
Skippy le Grand Gourou

36

Ще одна проблема, яку слід пам’ятати, полягає в тому, що 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"

Number.prototype.minFixed = функція (десяткових знаків) {return this.toFixed (десяткових знаків) .replace (/ \.? 0 * $ /, ""); }
Люк Блум

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

1
Останні нулі можуть дратувати, але саме це обіцяє зробити назва методу "toFixed";)
ksadowski


6

Існує проблема з усіма цими рішеннями, що плавають навколо, використовуючи множники. І рішення Kkyy, і Крістофа, на жаль, помиляються.

Перевірте свій код на номер 551.175 з двома знаками після коми - він закрутить до 551.17, тоді як він повинен бути 551.18 ! Але якщо ви перевірите на екс. 451.175 буде добре - 451.18. Тому важко помітити цю помилку з першого погляду.

Проблема полягає у множенні: спробуйте 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;
}

1
Ось проблема з арифметикою в js: (551.175 * 10 * 10)! == (551.175 * 100). Ви повинні використовувати десяткові кроки для переміщення комами для нереальних результатів десяткової.
Кір Канос

+1, щоб помітити це, але toFixedце також впливає - (0.335).toFixed(2) == 0.34 == (0.345).toFixed(2)… Який би метод не застосовувався, краще додати епсилон перед округленням.
Skippy le Grand Gourou

5

Я думаю, ключовим тут є спочатку правильно закріпити їх, а потім перетворити його на String.

function roundOf(n, p) {
    const n1 = n * Math.pow(10, p + 1);
    const n2 = Math.floor(n1 / 10);
    if (n1 >= (n2 * 10 + 5)) {
        return (n2 + 1) / Math.pow(10, p);
    }
    return n2 / Math.pow(10, p);
}

// All edge cases listed in this thread
roundOf(95.345, 2); // 95.35
roundOf(95.344, 2); // 95.34
roundOf(5.0364342423, 2); // 5.04
roundOf(0.595, 2); // 0.60
roundOf(0.335, 2); // 0.34
roundOf(0.345, 2); // 0.35
roundOf(551.175, 2); // 551.18
roundOf(0.3445434, 2); // 0.34

Тепер ви можете сміливо відформатувати це значення за допомогою toFixed (p). Отже, з вашим конкретним випадком:

roundOf(0.3445434, 2).toFixed(2); // 0.34

3

Якщо ви хочете, щоб рядок без круглого, ви можете використовувати цей RegEx (можливо, це не найефективніший спосіб ... але це дуже просто)

(2.34567778).toString().match(/\d+\.\d{2}/)[0]
// '2.34'

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

чудова відповідь, за винятком того, що у вас відсутні крапки з комою (Ні, в es6 крапки з комою не застаріли, і ми все одно повинні їх використовувати в деяких випадках). Я повинен був також змінити останній рядок: в return float_part ? int_part+'.'+float_part : int_part;іншому випадку , якщо ви пройшли Integer, він повертається номер з крапкою в кінці (приклад введення: 2100, вихід: 2100.)
Kuba Симоновський

0

Можливо, вам також захочеться десятковий роздільник? Ось функція, яку я щойно зробив:

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;
}

0

Не можна уникнути неузгодженого округлення цін із фактичним значенням x.xx5, використовуючи або множення, або ділення. Якщо вам потрібно обчислити правильні ціни на стороні клієнта, вам слід зберігати всі суми в центах. Це пов’язано з характером внутрішнього подання числових значень у JavaScript. Зауважте, що Excel страждає від тих самих проблем, тому більшість людей не помічають дрібних помилок, викликаних цим явищем. Однак помилки можуть накопичуватися кожного разу, коли ви додаєте багато обчислених значень, навколо цього існує ціла теорія, що включає порядок обчислень та інші методи, щоб мінімізувати помилку в кінцевому результаті. Щоб наголосити на проблемах з десятковими значеннями, зауважте, що 0,1 + 0,2 не точно відповідає 0,3 в JavaScript, тоді як 1 + 2 дорівнює 3.


рішення полягає в тому, щоб розділити цілу частину і десяткову частину і представити їх як цілі числа в базі 10, замість використання плаваючих елементів, тут вона працює без проблем для доситьPrint, але в цілому ви повинні вибрати між базовою та іншою, представництвом для реальні числа та інше, у кожного є свої проблеми
збирається

"Excel страждає від тих же проблем". джерело?
gaurav5430

0
/** 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"

0

Я використовую цей код для форматування плавців. Він заснований на, toPrecision()але позбавляє зайвих нулів. Я б вітав пропозиції щодо спрощення регулярного вираження.

function round(x, n) {
    var exp = Math.pow(10, n);
    return Math.floor(x*exp + 0.5)/exp;
}

Приклад використання:

function test(x, n, d) {
    var rounded = rnd(x, d);
    var result = rounded.toPrecision(n);
    result = result.replace(/\.?0*$/, '');
    result = result.replace(/\.?0*e/, 'e');
    result = result.replace('e+', 'e');
    return result;  
}

document.write(test(1.2000e45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2000e+45, 3, 2) + '=' + '1.2e45' + '<br>');
document.write(test(1.2340e45, 3, 2) + '=' + '1.23e45' + '<br>');
document.write(test(1.2350e45, 3, 2) + '=' + '1.24e45' + '<br>');
document.write(test(1.0000, 3, 2) + '=' + '1' + '<br>');
document.write(test(1.0100, 3, 2) + '=' + '1.01' + '<br>');
document.write(test(1.2340, 4, 2) + '=' + '1.23' + '<br>');
document.write(test(1.2350, 4, 2) + '=' + '1.24' + '<br>');
Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.