Dalam bahasa yang tidak memungkinkan garis bawah dalam bilangan bulat integer , apakah itu ide yang baik untuk membuat konstanta untuk 1 miliar? misalnya dalam C ++:
size_t ONE_BILLION = 1000000000;
Tentu saja, kita tidak boleh membuat konstanta untuk angka kecil seperti 100. Tetapi dengan 9 nol, bisa dibilang mudah untuk meninggalkan nol atau menambahkan satu lagi dalam kode seperti ini:
tv_sec = timeInNanosec / 1000000000;
tv_nsec = timeInNanosec % 1000000000;
coding-style
Martin C. Martin
sumber
sumber
1e9
,10^9
atau1_000_000_000
jika bahasa yang Anda gunakan mendukungnya.Jawaban:
Sebagian besar bahasa menampilkan semacam notasi eksponensial. Satu juta adalah
1e6
, (artinya 1 kali 10 pangkat 6). Ini pada dasarnya memecahkan masalah lebih baik daripada kebanyakan proposisi di sini.Dalam banyak bahasa mirip-C, notasi ilmiah mendefinisikan tipe floating point , yang sangat disayangkan jika Anda benar-benar membutuhkan int. Namun, Anda dapat dengan mudah mengetikkan konstanta itu untuk menghindari konversi tersirat di formular Anda.
n / int(1e9)
akan membagi dengan satu miliar.Dalam contoh Anda, berurusan dengan jumlah fisik (waktu dalam nanodetik), saya biasanya akan bertanya pada diri sendiri apakah bilangan bulat adalah tipe yang tepat. Bahkan titik mengambang
double
mungkin lebih cocok ketika berhadapan dengan jumlah yang terukur (walaupun tentu saja ada kasus di mana Anda lebih suka along long
).sumber
long long
rentang.Buat yang disebut NANOSECONDS_IN_ONE_SECOND sebagai gantinya.
Atau nama yang lebih pendek dan lebih baik jika Anda bisa memikirkannya.
sumber
Nanoseconds_Per_Second
tetapi ini, menurut pendapat saya, jawaban yang benar.NANOSECONDS
tidak ada artinya karena Anda tidak bisa mengatakan apa yang seharusnya diterapkan. Demikian juga,NANOSECONDS_PER_MICROSECOND
adalah konstanta valid serupa yang masuk akal.1mm/1m = 1000
, Yang merupakan persis titik apa yang sedang dilakukan di sini.NS_PER_SEC
harus jelas bagi siapa saja yang seharusnya berurusan dengan nanodetik.Konstanta dimaksudkan untuk memberi makna angka. Tidak ada arti tambahan
ONE_BILLION
untuk1000000000
. Sebenarnya, itu membuatnya lebih membingungkan, karena dalam bahasa alami yang berbeda, satu miliar berarti sesuatu yang berbeda (baik seribu juta atau sejuta juta)! Jika Anda ingin menulisnya lebih pendek, ada kemungkinan bahasa pemrograman Anda memungkinkan penggunaan notasi ilmiah, yaitu1e9
. Kalau tidak, saya setuju dengan @JohnB, bahwa angka ini benar-benar berarti jumlah nanodetik dalam sedetik, jadi sebutkan saja.sumber
Untuk satu atau dua penggunaan, saya akan menggunakan konvensi:
Ini sangat jelas, bisa dikompilasi menjadi konstan dan sulit untuk dikacaukan.
Juga, ini sangat berguna dalam kasus-kasus seperti:
di mana mudah untuk melihat kita berbicara tentang satu hari dalam hitungan detik.
sumber
instance.Time = ...
, tapi kemudian saya membungkamnya ...(1000 * 1000 * 1000)
adalah tipeint
, yang hanya diperlukan 16 bit, sehingga bisa meluap. Anda dapat menulis(1000L * 1000L * 1000L)
untuk menghindarinya.Panjang nilainya bukan yang menentukan apakah konstanta diperlukan atau tidak.
Anda menggunakan konstanta untuk menghindari angka ajaib , bukan untuk menghindari mengetik.
Misalnya ini adalah konstanta yang benar-benar valid:
Menggunakan:
(contoh kode di Jawa, terjemahkan ke bahasa favorit Anda)
sumber
Miliaran orang Amerika atau Eropa?
(atau dalam istilah teknis, satu miliar dalam skala pendek atau panjang - satu adalah 1.000 juta, yang lain adalah satu juta juta).
Mengingat kebingungan ini, maka saya akan mengatakan ya - masuk akal untuk mendefinisikannya sekali dan tetap menggunakannya, demikian juga berlaku untuk konstanta yang Anda perlukan untuk menyetujui definisi tentang - mendefinisikannya sekali.
sumber
Alasan untuk tidak
Pertama, inilah alasan mengapa tidak menulis garis bawah atau menggunakan trik apa pun untuk mensimulasikannya: ini membuat konstanta lebih sulit ditemukan dalam kode. Misalkan beberapa program menunjukkan, di suatu tempat dalam operasinya, nilai hard-code 1500000 untuk beberapa parameter. Saya ingin tahu di mana dalam kode sumber program ini sebenarnya terjadi, jadi saya ambil kodenya
1500000
, dan tidak menemukan apa pun. Mengapa? Mungkin dalam heksadesimal (tapi mengapa untuk angka desimal bulat). Tanpa sepengetahuan saya, konstanta sebenarnya ditulis sebagai1_500_000
. Saya membutuhkan regex1_?500_?000
.Membimbing Karakter dalam Komentar
Hanya karena satu jenis alat bantu visual tidak tersedia, atau kami tidak ingin menggunakannya karena alasan di atas, tidak berarti kami tidak dapat memanfaatkan dua dimensi file teks untuk membuat alat bantu visual alternatif:
Dengan ini kita dapat dengan mudah meyakinkan diri sendiri bahwa ada tiga kelompok tiga nol. Namun, kami masih dapat menangkap kode sumber untuk
1000000000
dan menemukannya.Pewarnaan Sintaks
Editor teks dengan pewarnaan sintaks yang dapat diprogram dapat dibuat untuk mewarnai kelompok digit dalam konstanta numerik dengan warna bergantian untuk keterbacaan yang lebih baik. Kami tidak perlu melakukan apa pun dalam kode.
Preprocessing: C, C ++, Objective C
Sekarang, jika kita benar-benar menginginkan beberapa koma di antara digit, di C dan C ++ kita dapat menggunakan beberapa preprocessing:
Bekerja untuk angka seperti
TH(1,234,567,890)
.Makro mirip dengan TH juga bisa bekerja dengan token paste daripada aritmatika. Dalam preprocessor C,
##
operator biner ("token paste") dapat digunakan dalam tubuh makro untuk menempelkan dua operan menjadi satu token tunggal. Satu atau kedua operan bisa berupa argumen makro. Kelemahan di sini (menciptakan risiko bagi kami) adalah bahwa jika katenasi yang dihasilkan bukan token yang valid, perilaku tidak terdefinisi.Sekarang
Program C yang menempelkan pengidentifikasi dan menggunakan hasilnya untuk memberi nama variabel global dan fungsi yang ada dan mengerikan untuk bekerja dengan karena mereka tahan terhadap alat-alat seperti GNU id-utils dan ctags.
sumber
Ya, itu terdengar seperti ide yang masuk akal. Kesalahan DIGIT off-by-one bahkan lebih buruk daripada kesalahan off-by-one yang terkenal. Meskipun, itu dapat membuat orang lain bingung (termasuk diri Anda di masa depan) untuk membaca kode.
Nama yang lebih jelas seperti NANOSEC_PER_SEC tampaknya bagus, karena akan menambah kejelasan tempat digunakannya waktu. Namun, tidak masuk akal untuk digunakan dalam konteks selain waktu, dan tidak praktis untuk membuat 1.000.000.000 terpisah untuk setiap situasi.
Apa yang benar-benar ingin Anda lakukan, konyol seperti yang terlihat pada awalnya, adalah 'bagi lebih dari sec'. Ini menyisakan NANO_PER, yang tidak hanya bebas bahasa (10 ^ 9 di Amerika dan Eropa) tetapi juga bebas situasi (tidak membatasi unit), dan mudah untuk mengetik dan membaca.
sumber
Secara umum adalah ide yang buruk untuk menggunakan konstanta skalar untuk konversi satuan, dan jika Anda mendapati diri Anda membuat konstanta untuk hal-hal seperti itu, Anda melakukan konversi di tempat yang terlalu banyak.
Ketika Anda memiliki jumlah satu unit (katakanlah, 10 detik), dan ingin mengkonversi ke unit lain (yaitu nanodetik); inilah saat yang tepat untuk menggunakan sistem jenis bahasa Anda untuk memastikan bahwa unit benar-benar diskalakan sesuai keinginan Anda.
Membuat fungsi Anda mengambil
Nanoseconds
parameter, dan menyediakan operator konversi dan / atau konstruktor di kelas itu untukSeconds
,Minutes
, atau apa-Anda-. Di sinilah Andaconst int
atau#define
atau1e9
terlihat dalam jawaban lainnya milik.Ini menghindari variabel unit ambigu yang mengambang di sekitar kode Anda; dan mencegah seluruh petak bug dari tempat penggandaan / pembagian yang salah diterapkan, atau sudah diterapkan, atau kuantitas sebenarnya jarak bukannya waktu, atau ...
Juga, di kelas-kelas seperti itu ada baiknya membuat konstruksi dari skalarsprivate biasa dan menggunakan statis "MakeSeconds (int)" atau serupa untuk mencegah penggunaan nomor buram yang ceroboh.
Lebih khusus untuk contoh Anda, di C ++ lihat Boost.Chrono .
sumber
Saya pribadi tidak akan menganggap itu praktik yang baik untuk membuat konstanta kecuali jika harus konstan. Jika itu akan berada di beberapa tempat dan menetapkannya di bagian atas file untuk modifikasi / atau pengujian akan berguna maka benar-benar.
Jika itu hanya karena canggung mengetik? lalu tidak.
Secara pribadi jika saya mendapatkan kode orang lain yang memiliki konstanta yang didefinisikan, saya biasanya menganggap ini sebagai aspek penting dari kode. Misalnya tcp menjaga timer hidup, jumlah koneksi maksimum diperbolehkan. Jika saya harus men-debug itu, saya mungkin akan membayar banyak perhatian yang tidak dibutuhkan untuk itu mencoba mencari tahu mengapa / di mana itu digunakan.
sumber
Ketika Anda memikirkan mengapa Anda menulis "1 Miliar" dan bukan "1000000000" di judul pertanyaan Anda, Anda akan menyadari mengapa jawabannya adalah ya.
sumber
Jangan membuat konstanta untuk literal besar Anda. Anda akan membutuhkan konstanta untuk setiap literal tersebut, yang (menurut saya) adalah lelucon yang lengkap. Jika Anda benar-benar perlu membuat literal Anda lebih jelas tanpa bantuan hal-hal seperti penyorotan sintaks, Anda dapat (walaupun saya tidak mau) membuat fungsi atau makro untuk membuat hidup Anda "lebih mudah":
sumber
Saya akan melakukan ini:
atau
const int
SciMega = 1000 * 1000; const intSciGiga = 1000 *SciMega;Mengenai jumlah nanodetik per detik: nano adalah "kebalikan" dari giga.
Perhatikan "Sains" - untuk ilmiah, seperti di komputer, arti kilo, mega, giga dll berbeda: 1024 (2 ^ 10), 1024 * 1024 (2 ^ 20), dll. 2 megabita bukan 2.000.000 byte .UPDATE Commenter menunjukkan bahwa ada istilah khusus untuk eksponen digital 2: http://en.wikipedia.org/wiki/Mebibyte
sumber