Bagaimana cara mengumpulkan angka dalam Javascript?

159

Saya ingin menggunakan Javascript untuk mengumpulkan angka. Karena angkanya adalah mata uang, saya ingin mengumpulkannya seperti dalam contoh-contoh ini (2 poin desimal):

  • 192.168 => 192.20
  • 192.11 => 192.20
  • 192.21 => 192.30
  • 192.26 => 192.30
  • 192.20 => 192.20

Bagaimana cara mencapai ini menggunakan Javascript? Fungsi Javascript bawaan akan mengumpulkan angka berdasarkan logika standar (kurang dari 5 untuk mengumpulkan).

cyberfly
sumber

Jawaban:

313
/**
 * @param num The number to round
 * @param precision The number of decimal places to preserve
 */
function roundUp(num, precision) {
  precision = Math.pow(10, precision)
  return Math.ceil(num * precision) / precision
}

roundUp(192.168, 1) //=> 192.2
Andrew Marshall
sumber
2
@AndrewMarshall apa tujuan mengalikan, lalu membaginya dengan 10?
codecowboy
6
@codecowboy Jika Anda tidak, maka ceil()akan memberi Anda 193, jadi kami harus memastikan bahwa semua presisi yang ingin kami pertahankan adalah sebelum titik desimal. Kemudian kami melakukan operasi terbalik untuk mengembalikan nilai "asli".
Andrew Marshall
1
Jika Anda mendapatkan nomor seperti 192.19999999999997, Anda dapat melamar .toFixed(1)kenum
flamer.ohr
4
Dan bagi mereka yang bertanya-tanya bagaimana cara mengumpulkan ke nomor WHOLE terdekat, Anda hanya perlu Math.ceil (). Sisanya hanya untuk berurusan dengan desimal. Untuk menyelamatkan orang lain waktu yang dibutuhkan otak saya untuk mencapai itu!
Nigel B. Peck
Solusi ini memiliki bug: Math.ceil (0,0159 * 1000000000) / presisi. Anda akan mendapatkan sebagian kecil 0,015900001. Perlu menambahkan validasi rentang untuk presisi.
Frank
26

Agak terlambat, tetapi, dapat membuat fungsi javascript yang dapat digunakan kembali untuk tujuan ini:

// Arguments: number to round, number of decimal places
function roundNumber(rnum, rlength) { 
    var newnumber = Math.round(rnum * Math.pow(10, rlength)) / Math.pow(10, rlength);
    return newnumber;
}

Panggil fungsi sebagai

alert(roundNumber(192.168,2));
suryakiran
sumber
2
Ini bekerja dengan baik, tetapi OP bertanya bagaimana mengumpulkan angka, jadi Math.ceil harus digunakan di sini alih-alih Math.round.
kloddant
Jawaban ini lebih baik daripada jawaban yang diterima jika Anda ingin mengumpulkan dengan benar meskipun tempat desimal yang Anda tuju. Mis: 1,054 -> 1,05 1,055 -> 1,06 NAMUN di sini adalah kasing tepi: 1,005 -> 1 1,006 -> 1,01 DAN 1,015 -> 1,01 1,016 -> 1,02 Jadi hati-hati.
Jay K
21

Pembulatan normal akan bekerja dengan tweak kecil:

Math.round(price * 10)/10

dan jika Anda ingin mempertahankan format mata uang, Anda dapat menggunakan metode Angka .toFixed()

(Math.round(price * 10)/10).toFixed(2)

Meskipun ini akan membuatnya menjadi String =)

Shad
sumber
Math.round (192.11 * 100) / 100 -> 192.11
krtek
1
Yang kedua tidak perlu pembulatan, ini lebih sepertiprice.toFixed(2)
Michael Krelin - hacker
@Krtek ooops, Terima kasih sudah menangkapnya. Saya salah membaca pertanyaan. Jawaban diperbarui.
Shad
2
OP bertanya bagaimana mengumpulkan angka, jadi Math.ceil harus digunakan di sini, bukan Math.round.
kloddant
10

Sangat dekat dengan jawaban TheEye , tetapi saya mengubah sedikit hal untuk membuatnya bekerja:

var num = 192.16;
    
console.log(    Math.ceil(num * 10) / 10    );

Hoàng Long
sumber
2

OP mengharapkan dua hal:
A. untuk mengumpulkan ke persepuluhan yang lebih tinggi, dan
B. untuk menunjukkan nol di tempat keseratus (kebutuhan khas dengan mata uang).

Memenuhi kedua persyaratan tampaknya membutuhkan metode terpisah untuk masing-masing di atas. Inilah pendekatan yang dibangun berdasarkan jawaban yang disarankan suryakiran:

//Arguments: number to round, number of decimal places.

function roundPrice(rnum, rlength) {
    var newnumber = Math.ceil(rnum * Math.pow(10, rlength-1)) / Math.pow(10, rlength-1);
    var toTenths = newnumber.toFixed(rlength);
    return toTenths;
}

alert(roundPrice(678.91011,2)); // returns 679.00
alert(roundPrice(876.54321,2)); // returns 876.60

Catatan penting: solusi ini menghasilkan hasil yang sangat berbeda dengan angka negatif dan eksponensial.

Demi perbandingan antara jawaban ini dan dua yang sangat mirip, lihat 2 pendekatan berikut. Yang pertama hanya membulatkan ke seratus terdekat per biasanya, dan yang kedua hanya putaran ke yang terdekat seratus (lebih besar).

function roundNumber(rnum, rlength) { 
    var newnumber = Math.round(rnum * Math.pow(10, rlength)) / Math.pow(10, rlength);
    return newnumber;
}

alert(roundNumber(678.91011,2)); // returns 678.91

function ceilNumber(rnum, rlength) { 
    var newnumber = Math.ceil(rnum * Math.pow(10, rlength)) / Math.pow(10, rlength);
    return newnumber;
}

alert(ceilNumber(678.91011,2)); // returns 678.92
Kay V
sumber
2

ok, ini sudah dijawab, tapi saya pikir Anda mungkin ingin melihat jawaban saya yang memanggil fungsi math.pow () sekali. Saya kira saya suka menjaga barang-barang KERING.

function roundIt(num, precision) {
    var rounder = Math.pow(10, precision);
    return (Math.round(num * rounder) / rounder).toFixed(precision)
};

Ini semacam menyatukan semuanya. Ganti Math.round () dengan Math.ceil () untuk mengumpulkan alih-alih pembulatan, itulah yang diinginkan OP.

John Grabauskas
sumber
1

fungsi ini membatasi desimal tanpa angka bulat

function limitDecimal(num,decimal){
     return num.toString().substring(0, num.toString().indexOf('.')) + (num.toString().substr(num.toString().indexOf('.'), decimal+1));
}
Behnam Mohammadi
sumber
Sebagai alternatif yang lebih pendek: return ('' + num) .split ('.'). Shift ()
Roberto
terima kasih Roberto kode ini berfungsi, tetapi hilangkan semua desimal
Behnam Mohammadi
0

Saya telah menggunakan jawaban @AndrewMarshall untuk waktu yang lama, tetapi menemukan beberapa kasus tepi. Tes berikut tidak lulus:

equals(roundUp(9.69545, 4), 9.6955);
equals(roundUp(37.760000000000005, 4), 37.76);
equals(roundUp(5.83333333, 4), 5.8333);

Inilah yang sekarang saya gunakan untuk mengumpulkan perilaku yang benar:

// 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);
    };
  }
})();

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

Sumber: https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Math/round

Nicolas BADIA
sumber
1
Kasing uji Anda tampaknya salah. roundUp(37.760000000000005, 4)harus 37.7601, dan roundUp(5.83333333, 4)seharusnya 5.8334. Keduanya (dan yang pertama) semuanya berlaku untuk fn yang saya berikan.
Andrew Marshall
@AndrewMarshall punya alasan, nilai yang Anda harapkan salah untuk kasus 2 dan 3.
Amn
-3

parseInt selalu dibulatkan ...

console.log(parseInt(5.8)+1);

do parseInt () +1

Omar
sumber