Bagaimana cara membulatkan angka float di javascript?

298

Saya perlu putaran misalnya 6.688689untuk 6.7, tapi selalu menunjukkan saya 7.

Metode saya:

Math.round(6.688689);
//or
Math.round(6.688689, 1);
//or 
Math.round(6.688689, 2);

Tetapi hasilnya selalu sama 7... Apa yang saya lakukan salah?

Vitalii Ponomar
sumber
28
(6.688689​).toFixed(1);
Shadow Wizard adalah Ear For You
Lihat ini
raina77ow
kemungkinan duplikat angka bulat dalam JavaScript ke N tempat desimal - silakan gunakan pencarian sebelum Anda mengajukan pertanyaan baru.
Felix Kling
1
@ShadowWizard sudah benar. Namun, .toFixedmengembalikan sebuah string. Pastikan untuk memasukkan hasilnya Number(). Lihat jawaban yang diterima, dan lainnya.
Jordan Arseno

Jawaban:

534
Number((6.688689).toFixed(1)); // 6.7
davin
sumber
22
Konversi angka menjadi string dan kemudian kembali lagi? Itu tidak bisa cepat.
csl
tidak baik jika angka Anda memiliki desimal kurang dari yang dibutuhkan. Ia menambahkan beberapa
njzk2
2
seperti yang ditunjukkan oleh benchmark JS, ini lebih lambat dari metode
@fivedigit
13
Number((456.1235).toFixed(3)) -> 456.123, Number((1.235).toFixed(2)) -> 1.24... JavaSript Bodoh ...
NoOne
6
Ini mungkin TIDAK MELAKUKAN apa yang Anda harapkan! Hasilnya bahkan dapat bergantung pada browser, lihat pertanyaan ini: stackoverflow.com/q/566564/2224996
maja
199
var number = 6.688689;
var roundedNumber = Math.round(number * 10) / 10;
fivedigit
sumber
13
Ini tidak selalu berhasil. Ambil Math.round(1.005*100)/100contoh dari MDN
tybro0103
7
@ tybro0103 Floating point evil: 1.005 * 100 = 100.49999999999999(setidaknya di mesin JS yang saya coba). Itu sebabnya itu tidak bekerja dan mengapa Anda tidak boleh mengandalkan float menjadi sangat akurat.
sudo
1
Salah. Math.round (1.015 * 100) / 100 mengembalikan 1.01 bukannya 1.02
Marco Marsala
81

Gunakan toFixed()fungsi.

(6.688689).toFixed(); // equal to 7
(6.688689).toFixed(1); // equal to 6.7
(6.688689).toFixed(2); // equal to 6.69
rpeshkov
sumber
5
Ini mungkin TIDAK MELAKUKAN apa yang Anda harapkan! Hasilnya bahkan dapat bergantung pada browser, lihat pertanyaan ini: stackoverflow.com/q/566564/2224996
maja
9
(6.688689) .toFixed (); sama dengan "7" bukan 7. Sama dengan contoh lainnya.
Vado
35

Pembaruan (2019-10). Berkat kode Reece Daniels di bawah ini sekarang tersedia sebagai satu set fungsi yang dikemas dalam paket npm-paket yang diharapkan (lihat).


Anda dapat menggunakan fungsi pembantu dari contoh MDN . Daripada Anda akan memiliki lebih banyak fleksibilitas:

Math.round10(5.25, 0);  // 5
Math.round10(5.25, -1); // 5.3
Math.round10(5.25, -2); // 5.25
Math.round10(5, 0);     // 5
Math.round10(5, -1);    // 5
Math.round10(5, -2);    // 5

Pembaruan (2019-01-15). Sepertinya dokumen MDN tidak lagi memiliki fungsi pembantu ini. Berikut cadangan dengan contoh:

// Closure
(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;
    }
    // If the value is negative...
    if (value < 0) {
      return -decimalAdjust(type, -value, exp);
    }
    // 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);
    };
  }
})();

Contoh penggunaan:

// 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
Math.round10(-1.005, -2);  // -1.01
// 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
aspanchenko
sumber
2
?? "Math.round10 bukan fungsi"
Peter Krauss
1
Saya menemukan ini sangat berguna sehingga memukulnya dalam paket npm cepat bagi mereka yang ingin menggunakannya tanpa kembung kode tambahan. Dikreditkan @aspanchenko dengan jawaban asli juga: npmjs.com/package/expected-round
Reece Daniels
19
> +(6.688687).toPrecision(2)
6.7

Sebuah Numberobjek dalam JavaScript memiliki metode yang tidak persis apa yang Anda butuhkan. Metode itu adalah Number.toPrecision([precision]).

Sama seperti .toFixed(1)itu mengubah hasil menjadi string, dan perlu dikonversi kembali menjadi angka. Selesai menggunakan +awalan di sini.

patokan sederhana di laptop saya:

number = 25.645234 typeof number
50000000 x number.toFixed(1) = 25.6 typeof string / 17527ms
50000000 x +(number.toFixed(1)) = 25.6 typeof number / 23764ms
50000000 x number.toPrecision(3) = 25.6 typeof string / 10100ms
50000000 x +(number.toPrecision(3)) = 25.6 typeof number / 18492ms
50000000 x Math.round(number*10)/10 = 25.6 typeof number / 58ms
string = 25.645234 typeof string
50000000 x Math.round(string*10)/10 = 25.6 typeof number / 7109ms
Evgeny
sumber
Menurut pendapat saya ini adalah jawaban terbaik (terbaik dalam hal praktik terbaik, pendekatan paling mudah).
cezar
1
1e-10.toPrecision(3): "1.00e-10" - ini putaran ke angka yang signifikan .
Vsevolod Golovanov
9

Jika Anda tidak hanya ingin menggunakan toFixed()tetapi juga ceil()dan floor()pada pelampung maka Anda dapat menggunakan fungsi berikut:

function roundUsing(func, number, prec) {
    var tempnumber = number * Math.pow(10, prec);
    tempnumber = func(tempnumber);
    return tempnumber / Math.pow(10, prec);
}

Menghasilkan:

> roundUsing(Math.floor, 0.99999999, 3)
0.999
> roundUsing(Math.ceil, 0.1111111, 3)
0.112

UPD:

Cara lain yang mungkin adalah ini:

Number.prototype.roundUsing = function(func, prec){
    var temp = this * Math.pow(10, prec)
    temp = func(temp);
    return temp / Math.pow(10, prec)
}

Menghasilkan:

> 6.688689.roundUsing(Math.ceil, 1)
6.7
> 6.688689.roundUsing(Math.round, 1)
6.7
> 6.688689.roundUsing(Math.floor, 1)
6.6
Dennis Yarmosh
sumber
bagaimana cara kita memutuskan kapan harus menggunakan langit-langit, lantai atau bundar untuk pembulatan? Sebagai contoh: roundUsing (Math.round, 1.015, 2) roundUsing (Math.ceil, 1.015, 2) memberikan 2 nilai berbeda Bagaimana kita tahu yang mana yang akan digunakan
gaurav5430
7

Fungsi putaran saya yang diperluas:

function round(value, precision) {
  if (Number.isInteger(precision)) {
    var shift = Math.pow(10, precision);
    // Limited preventing decimal issue
    return (Math.round( value * shift + 0.00000000000001 ) / shift);
  } else {
    return Math.round(value);
  }
} 

Contoh Output:

round(123.688689)     // 123
round(123.688689, 0)  // 123
round(123.688689, 1)  // 123.7
round(123.688689, 2)  // 123.69
round(123.688689, -2) // 100
round(1.015, 2) // 1.02
Nick Tsai
sumber
1
ini mirip dengan jawaban @ fivedigit. ronde (1.015, 2) masih memberikan 1.01 bukannya 1.02
gaurav5430
@ gaurav5430, terima kasih atas laporan Anda, saya telah memperbaikinya.
Nick Tsai
6

Lihat di bawah

var original = 28.59;

var result=Math.round(original*10)/10 akan mengembalikan Anda kembali 28.6

Semoga ini yang kamu mau ..

Fahim Parkar
sumber
7
"Jika saya punya uang receh untuk setiap kali saya melihat seseorang menggunakan FLOAT untuk menyimpan mata uang, saya akan memiliki $ 999.997634" - Bill Karwin.
emix
2
Salah. Math.round (1.015 * 100) / 100
Marco Marsala
3
float(value,ndec);
function float(num,x){
this.num=num;
this.x=x;
var p=Math.pow(10,this.x);
return (Math.round((this.num).toFixed(this.x)*p))/p;
}
Celestin Sv
sumber
2

Saya pikir fungsi ini dapat membantu.

 function round(value, ndec){
    var n = 10;
    for(var i = 1; i < ndec; i++){
        n *=10;
    }

    if(!ndec || ndec <= 0)
        return Math.round(value);
    else
        return Math.round(value * n) / n;
}


round(2.245, 2) //2.25
round(2.245, 0) //2
Jefferson Ribeiro
sumber
mirip dengan beberapa jawaban lain, ini gagal untuk putaran (1.015, 2), yang seharusnya memberi 1,02
gaurav5430
1

Saya pikir fungsi di bawah ini dapat membantu

function roundOff(value,round) {
   return (parseInt(value * (10 ** (round + 1))) - parseInt(value * (10 ** round)) * 10) > 4 ? (((parseFloat(parseInt((value + parseFloat(1 / (10 ** round))) * (10 ** round))))) / (10 ** round)) : (parseFloat(parseInt(value * (10 ** round))) / ( 10 ** round));
}

penggunaan: roundOff(600.23458,2);akan kembali600.23

KRISHNA TEJA
sumber
Bisakah Anda menjelaskan apa yang ditambahkan jawaban ini yang belum dicakup oleh jawaban sebelumnya?
stealththeninja
mirip dengan beberapa jawaban lain, ini gagal untuk putaran (1.015, 2), yang seharusnya memberi 1,02
gaurav5430
1

jika Anda berada di bawah konteks node.js, Anda dapat mencoba mathjs

const math = require('mathjs')
math.round(3.1415926, 2) 
// result: 3.14
hexcola
sumber
1

Ada alternatif .toLocaleString () untuk memformat angka, dengan banyak pilihan mengenai lokal, pengelompokan, pembentukan mata uang, notasi. Beberapa contoh:

Bulat ke 1 desimal, kembalikan float:

const n = +6.688689.toLocaleString('fullwide', {maximumFractionDigits:1})
console.log(
  n, typeof n
)

Membulatkan menjadi 2 desimal, memformat sebagai mata uang dengan simbol yang ditentukan, menggunakan pengelompokan koma untuk ribuan:

console.log(
  68766.688689.toLocaleString('fullwide', {maximumFractionDigits:2, style:'currency', currency:'USD', useGrouping:true})   
)

Format sebagai mata uang lokal :

console.log(
  68766.688689.toLocaleString('fr-FR', {maximumFractionDigits:2, style:'currency', currency:'EUR'})   
)

Bulat ke minimum 3 desimal, paksa angka nol untuk ditampilkan:

console.log(
  6.000000.toLocaleString('fullwide', {minimumFractionDigits:3})
)

Persen gaya untuk rasio. Masukan * 100 dengan tanda%

console.log(
  6.688689.toLocaleString('fullwide', {maximumFractionDigits:2, style:'percent'})
)

NVRM
sumber
1
+((6.688689 * (1 + Number.EPSILON)).toFixed(1)); // 6.7
+((456.1235 * (1 + Number.EPSILON)).toFixed(3)); // 456.124
Thanh Nguyễn Chí
sumber
1

Saya punya solusi yang sangat baik jika toFixed () tidak berfungsi.

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

Contoh

roundOff(10.456,2) //output 10.46
Ashish Gondaliya
sumber
0

Jika Anda menggunakan Browserify hari ini, Anda harus mencoba: roundTo lib NPM yang sangat berguna

peterb
sumber
0

Tweak kecil untuk jawaban ini :

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

roundToStep(2.55, 0.1) = 2.6
roundToStep(2.55, 0.01) = 2.55
roundToStep(2, 0.01) = 2
Crashalot
sumber
roundToStep (1,015, 0,002) memberi 1,014. adalah bahwa cara yang benar untuk menggunakannya
gaurav5430
@ gaurav5430 tryroundToStep(1.015, 0.001)
Crashalot