Saya mencoba memotong angka desimal menjadi tempat desimal. Sesuatu seperti ini:
5.467 -> 5.46
985.943 -> 985.94
toFixed(2)
tidak hanya tentang hal yang benar tetapi membulatkan nilainya. Saya tidak ingin nilainya dibulatkan. Semoga ini mungkin dalam javascript.
Jawaban:
upd :
Jadi, bagaimanapun, ternyata, bug pembulatan akan selalu menghantui Anda, tidak peduli seberapa keras Anda mencoba memberi kompensasi kepada mereka. Oleh karena itu, masalah harus ditangani dengan merepresentasikan angka persis dalam notasi desimal.
Number.prototype.toFixedDown = function(digits) { var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"), m = this.toString().match(re); return m ? parseFloat(m[1]) : this.valueOf(); }; [ 5.467.toFixedDown(2), 985.943.toFixedDown(2), 17.56.toFixedDown(2), (0).toFixedDown(1), 1.11.toFixedDown(1) + 22]; // [5.46, 985.94, 17.56, 0, 23.1]
Solusi lama yang rawan kesalahan berdasarkan kompilasi dari orang lain:
Number.prototype.toFixedDown = function(digits) { var n = this - Math.pow(10, -digits)/2; n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56" return n.toFixed(digits); }
sumber
1.11.toFixedDown(1) + 22
berakhir sebagai1.122
pengganti23.1
. Juga0.toFixedDown(1)
harus memproduksi0
tetapi malah menghasilkan-0.1
.(-10.2131).toFixedDown(2) // ==> 10.21
.(1e-7).toFixedDown(0) // ==> 1e-7
,. Apakah itu untuk1e-(>=7)
(ex:1e-8
,1e-9
, ...).Jawaban Dogbert bagus, tetapi jika kode Anda mungkin harus berurusan dengan angka negatif,
Math.floor
dengan sendirinya dapat memberikan hasil yang tidak terduga.Misalnya
Math.floor(4.3) = 4
, tapiMath.floor(-4.3) = -5
Gunakan fungsi pembantu seperti ini untuk mendapatkan hasil yang konsisten:
truncateDecimals = function (number) { return Math[number < 0 ? 'ceil' : 'floor'](number); }; // Applied to Dogbert's answer: var a = 5.467; var truncated = truncateDecimals(a * 100) / 100; // = 5.46
Berikut versi yang lebih nyaman dari fungsi ini:
truncateDecimals = function (number, digits) { var multiplier = Math.pow(10, digits), adjustedNum = number * multiplier, truncatedNum = Math[adjustedNum < 0 ? 'ceil' : 'floor'](adjustedNum); return truncatedNum / multiplier; }; // Usage: var a = 5.467; var truncated = truncateDecimals(a, 2); // = 5.46 // Negative digits: var b = 4235.24; var truncated = truncateDecimals(b, -2); // = 4200
Jika itu bukan perilaku yang diinginkan, masukkan panggilan ke
Math.abs
di baris pertama:var multiplier = Math.pow(10, Math.abs(digits)),
EDIT: shendz dengan benar menunjukkan bahwa menggunakan solusi ini dengan
a = 17.56
akan menghasilkan salah17.55
. Untuk mengetahui lebih lanjut tentang mengapa hal ini terjadi, baca Yang Harus Diketahui Setiap Ilmuwan Komputer Tentang Aritmatika Titik Mengambang . Sayangnya, menulis solusi yang menghilangkan semua sumber kesalahan floating-point cukup rumit dengan javascript. Dalam bahasa lain Anda akan menggunakan bilangan bulat atau mungkin tipe Desimal, tetapi dengan javascript ...Solusi ini harus 100% akurat, tetapi juga akan lebih lambat:
function truncateDecimals (num, digits) { var numS = num.toString(), decPos = numS.indexOf('.'), substrLength = decPos == -1 ? numS.length : 1 + decPos + digits, trimmedResult = numS.substr(0, substrLength), finalResult = isNaN(trimmedResult) ? 0 : trimmedResult; return parseFloat(finalResult); }
Bagi mereka yang membutuhkan kecepatan tetapi juga ingin menghindari kesalahan floating-point, cobalah sesuatu seperti BigDecimal.js . Anda dapat menemukan pustaka javascript BigDecimal lainnya dalam pertanyaan SO ini: "Apakah ada pustaka Javascript BigDecimal yang bagus?" dan inilah postingan blog yang bagus tentang perpustakaan matematika untuk Javascript
sumber
if(isNAN(result) result = 0;
Tergantung pada perilaku yang Anda inginkan.var a = 5.467; var truncated = Math.floor(a * 100) / 100; // = 5.46
sumber
truncate(-3.14)
dan menerima-4
kembali, saya pasti akan menyebutnya tidak diinginkan.var a = 65.1
var truncated = Math.floor(a * 100) / 100; // = 65.09
Karenanya ini bukan solusi yang tepatAnda dapat memperbaiki pembulatan dengan mengurangi 0,5 untuk toFixed, misalnya
(f - 0.005).toFixed(2)
sumber
Pertimbangkan mengambil keuntungan dari tilde ganda:
~~
.Perhatikan nomornya. Kalikan dengan angka signifikan setelah desimal sehingga Anda dapat memotongnya menjadi nol tempat dengan
~~
. Bagilah pengali itu kembali. Keuntungan.function truncator(numToTruncate, intDecimalPlaces) { var numPower = Math.pow(10, intDecimalPlaces); // "numPowerConverter" might be better return ~~(numToTruncate * numPower)/numPower; }
Saya mencoba untuk menolak membungkus
~~
panggilan dalam parens; urutan operasi harus membuat itu berfungsi dengan benar, saya yakin.alert(truncator(5.1231231, 1)); // is 5.1
alert(truncator(-5.73, 1)); // is -5.7
alert(truncator(-5.73, 0)); // is -5
Tautan JSFiddle .
EDIT: Melihat ke belakang, saya secara tidak sengaja juga menangani kasus untuk melengkapi kiri desimal juga.
alert(truncator(4343.123, -2)); // gives 4300.
Logikanya agak aneh mencari penggunaan itu, dan mungkin mendapat manfaat dari refactor cepat. Tapi masih berhasil. Lebih beruntung dari pada kebaikan.
sumber
Math
prototipe dengan ini dan memeriksa NaN-s sebelum mengeksekusi, itu akan sempurna.truncator((10 * 2.9) / 100, 2)
mengembalikan 0,28 bukannya 0,29 ... jsfiddle.net/25tgrzq1Solusi satu baris yang bagus:
function truncate (num, places) { return Math.trunc(num * Math.pow(10, places)) / Math.pow(10, places); }
Kemudian sebut dengan:
truncate(3.5636232, 2); // returns 3.56 truncate(5.4332312, 3); // returns 5.433 truncate(25.463214, 4); // returns 25.4632
sumber
Saya pikir saya akan memberikan jawaban menggunakan
|
karena sederhana dan berfungsi dengan baik.truncate = function(number, places) { var shift = Math.pow(10, places); return ((number * shift) | 0) / shift; };
sumber
or
ing dengan 0 berarti "simpan saja apa yang sudah kumiliki". Melakukan apa yang~~
dilakukan jawaban saya , tetapi dengan operasi bitwise tunggal. Meskipun memiliki batasan yang sama seperti yang tertulis juga: Kami tidak bisa melebihi 2 ^ 31 .truncate((10 * 2.9) / 100);
kode ini mengembalikan 0,28 alih-alih 0,29 jsfiddle.net/9pf0732dPangkas menggunakan operator bitwise:
~~0.5 === 0 ~~(-0.5) === 0 ~~14.32794823 === 14 ~~(-439.93) === -439
sumber
@ Jawaban Dogbert dapat ditingkatkan dengan
Math.trunc
, yang memotong alih-alih pembulatan.var a = 5.467; var truncated = Math.trunc(a * 100) / 100; // = 5.46
var a = -5.467; var truncated = Math.trunc(a * 100) / 100; // = -5.46
sumber
Math.trunc
, tetapi bukan9.28 * 100
merupakan927.9999
bukan928
. Anda mungkin ingin membaca The Perils of Floating PointSaya menulis jawaban menggunakan metode yang lebih pendek. Inilah yang saya pikirkan
function truncate(value, precision) { var step = Math.pow(10, precision || 0); var temp = Math.trunc(step * value); return temp / step; }
Metodenya bisa digunakan seperti itu
truncate(132456.25456789, 5)); // Output: 132456.25456 truncate(132456.25456789, 3)); // Output: 132456.254 truncate(132456.25456789, 1)); // Output: 132456.2 truncate(132456.25456789)); // Output: 132456
Atau, jika Anda menginginkan sintaks yang lebih pendek, ini dia
function truncate(v, p) { var s = Math.pow(10, p || 0); return Math.trunc(s * v) / s; }
sumber
Number.prototype.trim = function(decimals) { var s = this.toString(); var d = s.split("."); d[1] = d[1].substring(0, decimals); return parseFloat(d.join(".")); } console.log((5.676).trim(2)); //logs 5.67
sumber
Menurut saya fungsi ini bisa menjadi solusi sederhana:
function trunc(decimal,n=2){ let x = decimal + ''; // string return x.lastIndexOf('.')>=0?parseFloat(x.substr(0,x.lastIndexOf('.')+(n+1))):decimal; // You can use indexOf() instead of lastIndexOf() } console.log(trunc(-241.31234,2)); console.log(trunc(241.312,5)); console.log(trunc(-241.233)); console.log(trunc(241.2,0)); console.log(trunc(241));
sumber
Saya menemukan masalah: mempertimbangkan situasi selanjutnya: 2.1 atau 1.2 atau -6.4
Bagaimana jika Anda ingin selalu 3 desimal atau dua atau berapa, jadi, Anda harus menyelesaikan angka nol di depan ke kanan
// 3 decimals numbers 0.5 => 0.500 // 6 decimals 0.1 => 0.10000 // 4 decimales -2.1 => -2.1000 // truncate to 3 decimals 3.11568 => 3.115
Ini adalah fungsi tetap dari Nick Knowlson
function truncateDecimals (num, digits) { var numS = num.toString(); var decPos = numS.indexOf('.'); var substrLength = decPos == -1 ? numS.length : 1 + decPos + digits; var trimmedResult = numS.substr(0, substrLength); var finalResult = isNaN(trimmedResult) ? 0 : trimmedResult; // adds leading zeros to the right if (decPos != -1){ var s = trimmedResult+""; decPos = s.indexOf('.'); var decLength = s.length - decPos; while (decLength <= digits){ s = s + "0"; decPos = s.indexOf('.'); decLength = s.length - decPos; substrLength = decPos == -1 ? s.length : 1 + decPos + digits; }; finalResult = s; } return finalResult; };
https://jsfiddle.net/huttn155/7/
sumber
x = 0.0000
testruncateDecimals (x, 2)
gagal. kembali0
. tidak seperti yang diharapkan0.00
function toFixed(number, digits) { var reg_ex = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)") var array = number.toString().match(reg_ex); return array ? parseFloat(array[1]) : number.valueOf() } var test = 10.123456789 var __fixed = toFixed(test, 6) console.log(__fixed) // => 10.123456
sumber
Jawaban dari @kirilloid sepertinya adalah jawaban yang benar, namun kode utama perlu diperbarui. Solusinya tidak menangani angka negatif (yang disebutkan seseorang di bagian komentar tetapi belum diperbarui di kode utama).
Memperbarui itu menjadi solusi lengkap yang diuji:
Number.prototype.toFixedDown = function(digits) { var re = new RegExp("([-]*\\d+\\.\\d{" + digits + "})(\\d)"), m = this.toString().match(re); return m ? parseFloat(m[1]) : this.valueOf(); };
Contoh Penggunaan:
var x = 3.1415629; Logger.log(x.toFixedDown(2)); //or use whatever you use to log
Riddle: JS Number Round down
PS: Repo tidak cukup untuk mengomentari solusi itu.
sumber
Berikut ini adalah fungsi sederhana namun berfungsi untuk memotong angka hingga 2 tempat desimal.
function truncateNumber(num) { var num1 = ""; var num2 = ""; var num1 = num.split('.')[0]; num2 = num.split('.')[1]; var decimalNum = num2.substring(0, 2); var strNum = num1 +"."+ decimalNum; var finalNum = parseFloat(strNum); return finalNum; }
sumber
Jenis yang dihasilkan tetap berupa angka ...
/* Return the truncation of n wrt base */ var trunc = function(n, base) { n = (n / base) | 0; return base * n; }; var t = trunc(5.467, 0.01);
sumber
Lodash memiliki beberapa metode utilitas Matematika yang dapat membulatkan , memberi lantai , dan langit - langit angka dengan ketepatan desimal tertentu. Ini meninggalkan nol tertinggal.
Mereka mengambil pendekatan yang menarik, menggunakan eksponen angka. Rupanya ini menghindari masalah pembulatan.
(Catatan:
func
adalahMath.round
atauceil
ataufloor
dalam kode di bawah)// Shift with exponential notation to avoid floating-point issues. var pair = (toString(number) + 'e').split('e'), value = func(pair[0] + 'e' + (+pair[1] + precision)); pair = (toString(value) + 'e').split('e'); return +(pair[0] + 'e' + (+pair[1] - precision));
Tautan ke kode sumber
sumber
Di sini pendapat saya tentang subjek:
convert.truncate = function(value, decimals) { decimals = (decimals === undefined ? 0 : decimals); return parseFloat((value-(0.5/Math.pow(10, decimals))).toFixed(decimals),10); };
Ini hanya versi yang sedikit lebih rumit
(f - 0.005).toFixed(2)
sumber
Salah satu yang ditandai sebagai solusi adalah solusi yang lebih baik yang saya temukan sampai hari ini, tetapi memiliki masalah serius dengan 0 (misalnya, 0.toFixedDown (2) menghasilkan -0.01). Jadi saya sarankan untuk menggunakan ini:
Number.prototype.toFixedDown = function(digits) { if(this == 0) { return 0; } var n = this - Math.pow(10, -digits)/2; n += n / Math.pow(2, 53); // added 1360765523: 17.56.toFixedDown(2) === "17.56" return n.toFixed(digits); }
sumber
Inilah yang saya gunakan:
var t = 1; for (var i = 0; i < decimalPrecision; i++) t = t * 10; var f = parseFloat(value); return (Math.floor(f * t)) / t;
sumber
const TO_FIXED_MAX = 100; function truncate(number, decimalsPrecison) { // make it a string with precision 1e-100 number = number.toFixed(TO_FIXED_MAX); // chop off uneccessary digits const dotIndex = number.indexOf('.'); number = number.substring(0, dotIndex + decimalsPrecison + 1); // back to a number data type (app specific) return Number.parseFloat(number); } // example truncate(0.00000001999, 8); 0.00000001
bekerja dengan:
sumber
hanya untuk menunjukkan solusi sederhana yang berhasil untuk saya
konversikan menjadi string dan kemudian regex ...
var number = 123.45678; var number_s = '' + number; var number_truncated_s = number_s.match(/\d*\.\d{4}/)[0] var number_truncated = parseFloat(number_truncated_s)
Itu bisa disingkat menjadi
var number_truncated = parseFloat(('' + 123.4568908).match(/\d*\.\d{4}/)[0])
sumber
Berikut adalah kode ES6 yang melakukan apa yang Anda inginkan
const truncateTo = (unRouned, nrOfDecimals = 2) => { const parts = String(unRouned).split("."); if (parts.length !== 2) { // without any decimal part return unRouned; } const newDecimals = parts[1].slice(0, nrOfDecimals), newString = `${parts[0]}.${newDecimals}`; return Number(newString); }; // your examples console.log(truncateTo(5.467)); // ---> 5.46 console.log(truncateTo(985.943)); // ---> 985.94 // other examples console.log(truncateTo(5)); // ---> 5 console.log(truncateTo(-5)); // ---> -5 console.log(truncateTo(-985.943)); // ---> -985.94
sumber
Number.prototype.truncate = function(places) { var shift = Math.pow(10, places); return Math.trunc(this * shift) / shift; };
sumber
Anda bisa bekerja dengan string. Ini Memeriksa apakah '.' ada, lalu menghapus bagian dari string.
memotong (7.88, 1) -> 7.8
memotong (7.889, 2) -> 7.89
memotong (-7.88, 1) -> -7.88
function truncate(number, decimals) { const tmp = number + ''; if (tmp.indexOf('.') > -1) { return +tmp.substr(0 , tmp.indexOf('.') + decimals+1 ); } else { return +number } }
sumber
Saya agak bingung mengapa ada begitu banyak jawaban berbeda untuk pertanyaan yang sangat sederhana; hanya ada dua pendekatan yang saya lihat yang tampaknya layak untuk dilihat. Saya melakukan benchmark cepat untuk melihat perbedaan kecepatan menggunakan https://jsbench.me/ .
Ini adalah solusi yang saat ini (26/9/2020) ditandai sebagai jawaban:
function truncate(n, digits) { var re = new RegExp("(\\d+\\.\\d{" + digits + "})(\\d)"), m = n.toString().match(re); return m ? parseFloat(m[1]) : n.valueOf(); }; [ truncate(5.467,2), truncate(985.943,2), truncate(17.56,2), truncate(0, 1), truncate(1.11, 1) + 22];
Namun, ini melakukan hal-hal string dan regex, yang biasanya tidak terlalu efisien, dan ada fungsi Math.trunc yang melakukan persis seperti yang diinginkan OP hanya tanpa desimal. Oleh karena itu, Anda dapat dengan mudah menggunakannya ditambah sedikit aritmatika tambahan untuk mendapatkan hal yang sama.
Berikut adalah solusi lain yang saya temukan di utas ini, yang akan saya gunakan:
function truncate(n, digits) { var step = Math.pow(10, digits || 0); var temp = Math.trunc(step * n); return temp / step; } [ truncate(5.467,2), truncate(985.943,2), truncate(17.56,2), truncate(0, 1), truncate(1.11, 1) + 22];
Metode pertama adalah "99.92% lebih lambat" dari yang kedua, jadi yang kedua pasti yang saya sarankan untuk digunakan.
Oke, kembali mencari cara lain untuk menghindari pekerjaan ...
sumber