Saya terus tersandung pada penentu format untuk keluarga fungsi printf (). Yang saya inginkan adalah bisa mencetak ganda (atau float) dengan jumlah digit maksimum setelah koma desimal. Jika saya menggunakan:
printf("%1.3f", 359.01335);
printf("%1.3f", 359.00999);
saya mendapat
359.013
359.010
Bukan yang diinginkan
359.013
359.01
Adakah yang bisa membantu saya?
Jawaban:
Ini tidak dapat dilakukan dengan penentu
printf
format normal . Yang paling dekat yang bisa Anda dapatkan adalah:tapi ".6" adalah lebar numerik total jadi
hancurkan.
Apa yang dapat Anda lakukan adalah
sprintf("%.20g")
memberikan nomor ke buffer string kemudian memanipulasi string tersebut agar hanya memiliki karakter N setelah titik desimal.Dengan asumsi bilangan Anda ada di variabel num, fungsi berikut akan menghapus semua kecuali
N
desimal pertama , lalu menghapus angka nol yang tertinggal (dan titik desimal jika semuanya nol).Jika Anda tidak senang dengan aspek pemotongan (yang akan berubah
0.12399
menjadi0.123
daripada membulatkannya0.124
), Anda sebenarnya dapat menggunakan fasilitas pembulatan yang sudah disediakan olehprintf
. Anda hanya perlu menganalisis angka sebelumnya untuk membuat lebar secara dinamis, lalu gunakan angka tersebut untuk mengubah angka menjadi string:Inti dari
nDecimals()
kasus ini adalah untuk menghitung lebar bidang dengan benar, lalu memformat angka menggunakan format string berdasarkan itu. Harness ujimain()
menunjukkan ini dalam tindakan:Setelah Anda memiliki nilai yang dibulatkan dengan benar, Anda dapat sekali lagi meneruskannya ke
morphNumericString()
untuk menghapus nol di belakang hanya dengan mengubah:ke:
(atau memanggil
morphNumericString
di akhirnDecimals
tapi, dalam hal ini, saya mungkin hanya menggabungkan keduanya menjadi satu fungsi), dan Anda berakhir dengan:sumber
.
Di beberapa lokal, tempat desimal sebenarnya adalah,
koma.atof
memberikan kembali nilai yang sama.0.10000000000000000555
akan menjadi0.1
ketika dilucuti kembali. Masalahnya mungkin muncul jika Anda memiliki nilai sedikit di bawah seperti jika representasi terdekat dari42.1
was42.099999999314159
. Jika Anda benar-benar ingin mengatasinya, maka Anda mungkin perlu membulatkan berdasarkan digit terakhir yang dihapus daripada dipotong.printf
fungsi -like karena mereka sudah mendukung parameter dinamis (*
karakter khusus): misalnyaprintf("%*.*f", total, decimals, x);
mengeluarkan angka dengan panjang bidang dan desimal total yang ditentukan secara dinamis.Untuk menghilangkan nol di belakangnya, Anda harus menggunakan format "% g":
Setelah pertanyaan diklarifikasi sedikit, bahwa menekan angka nol bukan satu-satunya hal yang ditanyakan, tetapi membatasi keluaran ke tiga tempat desimal juga diperlukan. Saya pikir itu tidak bisa dilakukan dengan string format sprintf saja. Seperti yang ditunjukkan Pax Diablo , manipulasi string akan diperlukan.
sumber
Saya suka jawaban R. sedikit diubah:
'1000' menentukan presisi.
Kekuatan ke pembulatan 0,5.
EDIT
Oke, jawaban ini diedit beberapa kali dan saya kehilangan jejak apa yang saya pikirkan beberapa tahun yang lalu (dan awalnya tidak memenuhi semua kriteria). Jadi inilah versi baru (yang memenuhi semua kriteria dan menangani angka negatif dengan benar):
Dan kasus uji:
Dan hasil dari tes:
Sekarang, semua kriteria terpenuhi:
Sayangnya jawaban ini adalah dua baris karena
sprintf
tidak mengembalikan string.sumber
Saya mencari string (mulai paling kanan) untuk karakter pertama dalam rentang
1
ke9
(nilai ASCII49
-57
) lalunull
(setel ke0
) setiap karakter di kanannya - lihat di bawah:sumber
Bagaimana dengan hal seperti ini (mungkin memiliki kesalahan pembulatan dan masalah nilai negatif yang perlu di-debug, ditinggalkan sebagai latihan untuk pembaca):
Ini sedikit terprogram tetapi setidaknya tidak membuat Anda melakukan manipulasi string apa pun.
sumber
Sebuah solusi sederhana tetapi menyelesaikan pekerjaan, menetapkan panjang dan presisi yang diketahui dan menghindari kemungkinan format eksponensial (yang merupakan risiko jika Anda menggunakan% g):
Tambahkan atau hapus "lain" jika Anda menginginkan maksimal 2 desimal; 4 desimal; dll.
Misalnya jika Anda menginginkan 2 desimal:
Jika Anda ingin menentukan lebar minimum untuk menjaga bidang sejajar, tambahkan sesuai kebutuhan, misalnya:
Anda juga dapat mengonversinya menjadi fungsi di mana Anda meneruskan lebar bidang yang diinginkan:
sumber
d = 0.0001
: kemudianfloor(d)
adalah0
, sehingga perbedaannya adalah lebih besar dari 0.000001, sehinggaDoubleEquals
adalah palsu, sehingga akan tidak menggunakan"%.0f"
specifier: Anda akan melihat membuntuti nol dari"%*.2f"
atau"%*.3f"
. Jadi itu tidak menjawab pertanyaan itu.Saya menemukan masalah di beberapa solusi yang diposting. Saya mengumpulkan ini berdasarkan jawaban di atas. Sepertinya itu berhasil untuk saya.
sumber
Beberapa solusi yang paling banyak dipilih menyarankan penentu
%g
konversiprintf
. Ini salah karena ada kasus dimana%g
notasi ilmiah akan dihasilkan. Solusi lain menggunakan matematika untuk mencetak jumlah digit desimal yang diinginkan.Saya pikir solusi termudah adalah dengan menggunakan
sprintf
dengan%f
specifier konversi dan untuk menghapus trailing nol dan mungkin titik desimal dari hasil secara manual. Berikut solusi C99:Perhatikan bahwa karakter yang digunakan untuk angka dan pemisah desimal bergantung pada lokal saat ini. Kode di atas mengasumsikan bahasa Inggris C atau AS.
sumber
Inilah percobaan pertama saya pada sebuah jawaban:
Bug yang diketahui: Kemungkinan buffer overflow bergantung pada format. Jika "." ada karena alasan lain selain% f hasil yang salah mungkin terjadi.
sumber
Mengapa tidak melakukan ini saja?
sumber
Sedikit variasi di atas:
Kode di sini:
Masih berpotensi meluap, jadi hati-hati; P
sumber
Saya akan mengatakan Anda harus menggunakan
printf("%.8g",value);
Jika Anda menggunakan
"%.6g"
Anda tidak akan mendapatkan hasil yang diinginkan untuk beberapa nomor seperti 32.230210 itu harus mencetak32.23021
tetapi mencetak32.2302
sumber
Kode Anda dibulatkan menjadi tiga tempat desimal karena ".3" sebelum f
Jadi jika baris kedua dibulatkan menjadi dua tempat desimal, Anda harus mengubahnya menjadi ini:
Kode itu akan menampilkan hasil yang Anda inginkan:
* Perhatikan ini dengan asumsi Anda sudah mencetaknya pada baris terpisah, jika tidak maka hal berikut akan mencegahnya mencetak pada baris yang sama:
Kode sumber program berikut adalah tes saya untuk jawaban ini
sumber