Apakah saya melewatkan sesuatu di sini?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Mengapa tidak.toFixed()
kembali string?
Saya ingin membulatkan angka menjadi 2 angka desimal.
Apakah saya melewatkan sesuatu di sini?
var someNumber = 123.456;
someNumber = someNumber.toFixed(2);
alert(typeof(someNumber));
//alerts string
Mengapa tidak.toFixed()
kembali string?
Saya ingin membulatkan angka menjadi 2 angka desimal.
Jawaban:
Ini mengembalikan string karena 0,1, dan kekuatannya (yang digunakan untuk menampilkan pecahan desimal), tidak dapat diwakili (setidaknya tidak dengan akurasi penuh) dalam sistem titik-mengambang biner.
Sebagai contoh, 0,1 benar-benar 0,1000000000000000055511151231257827021181583404541015625, dan 0,01 benar-benar 0,01000000000000000020816681711721685132943093776702880859375. (Terima kasih BigDecimal
telah membuktikan pendapat saya. :-P)
Oleh karena itu (tidak ada floating point desimal atau tipe angka rasional), mengeluarkannya sebagai string adalah satu-satunya cara untuk memangkasnya dengan presisi yang dibutuhkan untuk tampilan.
toFixed
adalah fungsi pemformatan, yang memiliki tujuan tunggal mengonversi angka menjadi string, memformatnya menggunakan jumlah desimal yang ditentukan. Alasan mengembalikan string adalah karena seharusnya mengembalikan string, dan jika itu dinamai toStringFixed
sebaliknya, OP tidak akan terkejut dengan hasilnya. Satu-satunya masalah di sini adalah bahwa OP diharapkan berfungsi Math.round
, tanpa berkonsultasi dengan referensi JS.
Number.prototype.toFixed
adalah fungsi yang dirancang untuk memformat angka sebelum mencetaknya. Itu dari keluarga toString
, toExponential
dantoPrecision
.
Untuk membulatkan angka, Anda akan melakukan ini:
someNumber = 42.008;
someNumber = Math.round( someNumber * 1e2 ) / 1e2;
someNumber === 42.01;
// if you need 3 digits, replace 1e2 with 1e3 etc.
// or just copypaste this function to your code:
function toFixedNumber(num, digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(num*pow) / pow;
}
.
Atau jika Anda menginginkan fungsi " mirip-asli ", Anda dapat memperluas prototipe:
Number.prototype.toFixedNumber = function(digits, base){
var pow = Math.pow(base||10, digits);
return Math.round(this*pow) / pow;
}
someNumber = 42.008;
someNumber = someNumber.toFixedNumber(2);
someNumber === 42.01;
//or even hexadecimal
someNumber = 0xAF309/256 //which is af3.09
someNumber = someNumber.toFixedNumber(1, 16);
someNumber.toString(16) === "af3.1";
Namun , ingatlah bahwa mencemari prototipe dianggap buruk ketika Anda menulis modul, karena modul tidak boleh memiliki efek samping. Jadi, untuk modul, gunakan fungsi pertama .
type Number
. Masalahnya adalah bahwa +(anyValue)
selalu mengembalikan angka - misalnya. +("45")
kembali 45
, +(new Number(42))
kembali 42
. Ini seperti mengetik fungsi dengan kuat. Jika Anda terbiasa, Anda dapat menghindari banyak bug :)
someNumber = Math.round( 42.008 * 1e2 ) / 1e2;
tidak 42.01
, itu ~42.0099999999999980
. Alasan: Nomor 42.01
itu tidak ada dan dibulatkan ke nomor terdekat yang ada. btw, nomor bukti dengan toPrecision(18)
mencetaknya dengan semua digit yang relevan.
Saya telah memecahkan masalah ini dengan mengubah ini:
someNumber = someNumber.toFixed(2)
...untuk ini:
someNumber = +someNumber.toFixed(2);
Namun ini akan mengubah angka menjadi string dan menguraikannya lagi, yang akan berdampak signifikan pada kinerja. Jika Anda peduli dengan kinerja atau keamanan jenis, periksa jawaban lainnya juga.
someNumber = Math.round(someNumber * 1e2) / 1e2
! Lihat jawaban saya untuk cara yang lebih umum.
Kenapa tidak digunakan parseFloat
?
var someNumber = 123.456;
someNumber = parseFloat(someNumber.toFixed(2));
alert(typeof(someNumber));
//alerts number
Tentu saja mengembalikan string. Jika Anda ingin membulatkan variabel numerik, Anda akan menggunakan Math.round (). Maksud dari toFixed adalah untuk memformat angka dengan jumlah tetap tempat desimal untuk ditampilkan kepada pengguna .
Apa yang Anda harapkan untuk dikembalikan ketika seharusnya memformat angka? Jika Anda memiliki nomor, Anda tidak bisa melakukan apa-apa karena mis 2 == 2.0 == 2.00
. Dll. Jadi harus berupa string.
Untuk memberikan contoh mengapa harus berupa string:
Jika Anda memformat 1.toFixed (2) Anda akan mendapatkan '1,00'.
Ini tidak sama dengan 1, karena 1 tidak memiliki 2 desimal.
Saya tahu JavaScript bukan bahasa kinerja , tetapi kemungkinan Anda akan mendapatkan kinerja yang lebih baik untuk pembulatan jika Anda menggunakan sesuatu seperti: roundedValue = Math.round (nilai * 100) * 0,01
Karena penggunaan utamanya adalah menampilkan angka? Jika Anda ingin membulatkan angka, gunakan Math.round()
dengan faktor yang sesuai.
'42'
merupakan angka ... yang bukan. Hanya karena sebuah string berisi digit saja tidak membuatnya menjadi angka. Ini bukan PHP. :-P
Inilah versi yang sedikit lebih fungsional dari jawaban yang m93a
diberikan.
const toFixedNumber = (toFixTo = 2, base = 10) => num => {
const pow = Math.pow(base, toFixTo)
return +(Math.round(num * pow) / pow)
}
const oneNumber = 10.12323223
const result1 = toFixedNumber(2)(oneNumber) // 10.12
const result2 = toFixedNumber(3)(oneNumber) // 10.123
// or using pipeline-operator
const result3 = oneNumber |> toFixedNumber(2) // 10.12