Saya telah menjelaskan kepada siswa saya bahwa pengujian sama dengan tidak dapat diandalkan untuk variabel float, tetapi baik untuk bilangan bulat. Buku teks yang saya gunakan mengatakan bahwa lebih mudah dibaca> dan <daripada> = dan <=. Saya setuju sampai batas tertentu, tetapi dalam lingkaran For? Bukankah lebih jelas untuk memiliki loop menentukan nilai awal dan akhir?
Apakah saya melewatkan sesuatu yang benar oleh penulis buku teks?
Contoh lain dalam tes Range seperti:
jika skor> 89 grade = 'A'
lain jika skor> 79 grade = 'B' ...
Mengapa tidak mengatakan saja: jika skor> = 90?
Jawaban:
Dalam bahasa pemrograman yang dikeriting keriting dengan array berbasis nol , biasanya untuk menulis
for
loop seperti ini:Ini melintasi semua elemen dalam array, dan sejauh ini merupakan kasus yang paling umum. Ini menghindari penggunaan
<=
atau>=
.Satu-satunya waktu yang harus diubah adalah ketika Anda harus melewati elemen pertama atau terakhir, atau melewatinya ke arah yang berlawanan, atau melewatinya dari titik awal yang berbeda atau ke titik akhir yang berbeda.
Untuk koleksi, dalam bahasa yang mendukung iterator, lebih umum untuk melihat ini:
Yang menghindari perbandingan sepenuhnya.
Jika Anda mencari aturan yang keras dan cepat tentang kapan harus menggunakan
<=
vs<
, tidak ada; gunakan apa yang terbaik mengekspresikan niat Anda. Jika kode Anda perlu mengekspresikan konsep "Kurang dari atau sama dengan 55 mil per jam," maka perlu dikatakan<=
, tidak<
.Untuk menjawab pertanyaan Anda tentang rentang nilai,
>= 90
lebih masuk akal, karena 90 adalah nilai batas aktual, bukan 89.sumber
for
loop seperti ini. Bentukfor
loop yang saya berikan di sini akan langsung dikenali oleh pengembang mana pun dengan sedikit pengalaman. Jika Anda menginginkan jawaban yang lebih spesifik berdasarkan skenario yang lebih spesifik, Anda harus memasukkannya dalam pertanyaan Anda.Itu tidak masalah.
Tetapi demi argumen, mari kita menganalisis dua opsi:
a > b
vsa >= b
.Tunggu sebentar! Itu tidak setara!
OK, lalu
a >= b -1
vsa > b
ataua > b
vsa >= b +1
.Hm,
a >b
dana >= b
keduanya terlihat lebih baik daripadaa >= b - 1
dana >= b +1
. Apa sih semua ini1
? Jadi saya berpendapat bahwa manfaat dari memiliki>
bukannya>=
atau sebaliknya dihilangkan dengan harus menambah atau mengurangi secara acak1
.Tapi bagaimana kalau itu angka? Apakah lebih baik mengatakan
a > 7
ataua >= 6
? Tunggu sebentar. Apakah kita benar-benar berdebat apakah lebih baik menggunakan>
vs>=
dan mengabaikan variabel kode keras? Jadi itu benar-benar menjadi pertanyaan apakaha > DAYS_OF_WEEK
lebih baik daria >= DAYS_OF_WEEK_MINUS_ONE
... atau itua > NUMBER_OF_LEGS_IN_INSECT_PLUS_ONE
vsa >= NUMBER_OF_LEGS_IN_INSECT
? Dan kita kembali menambahkan / mengurangi1
, hanya saja kali ini dalam nama variabel. Atau mungkin berdebat apakah yang terbaik adalah menggunakan ambang, batas, maksimum.Dan sepertinya tidak ada aturan umum: itu tergantung pada apa yang dibandingkan
Tapi sungguh, ada hal-hal yang jauh lebih penting untuk diperbaiki dalam kode seseorang dan pedoman yang jauh lebih objektif dan masuk akal (misalnya batas karakter-X per baris) yang masih memiliki pengecualian.
sumber
>
vs>=
atau diskusi tentang apakah diskusi>
vs>=
bermakna? walaupun mungkin sebaiknya menghindari mendiskusikan ini: pSecara komputasi tidak ada perbedaan biaya saat menggunakan
<
atau>
dibandingkan dengan<=
atau>=
. Ini dihitung sama cepatnya.Namun sebagian besar untuk loop akan dihitung dari 0 (karena banyak bahasa menggunakan 0 pengindeksan untuk array mereka). Jadi kanonik untuk loop dalam bahasa tersebut adalah
melakukan ini dengan
<=
mengharuskan Anda untuk menambahkan -1 di suatu tempat untuk menghindari kesalahan satu per satuatau
Tentu saja jika bahasa menggunakan pengindeksan berbasis 1 maka Anda akan menggunakan <= sebagai syarat pembatas.
Kuncinya adalah bahwa nilai-nilai yang dinyatakan dalam kondisi adalah yang dari deskripsi masalah. Lebih bersih untuk dibaca
untuk interval setengah terbuka daripada
dan harus melakukan perhitungan matematika untuk mengetahui bahwa tidak ada nilai yang memungkinkan antara 19 dan 20
sumber
for(markup = 5; markup <= MAX_MARKUP; ++markup)
. Hal lain akan terlalu rumit.Saya akan mengatakan bahwa intinya bukan apakah Anda harus menggunakan> atau> =. Intinya adalah menggunakan apa pun yang memungkinkan Anda menulis kode ekspresif.
Jika Anda merasa perlu menambah / mengurangi satu, pertimbangkan untuk menggunakan operator lain. Saya menemukan bahwa hal-hal baik terjadi ketika Anda memulai dengan model domain yang baik. Kemudian logika menulis sendiri.
Ini jauh lebih ekspresif daripada
Dalam kasus lain, cara lain lebih disukai:
Lebih baik dari
Maafkan "obsesi primitif". Jelas Anda ingin menggunakan jenis Velocity- dan Money-type di sini, tetapi saya menghilangkannya untuk singkatnya. Intinya adalah: Gunakan versi yang lebih ringkas dan yang memungkinkan Anda fokus pada masalah bisnis yang ingin Anda selesaikan.
sumber
Seperti yang Anda tunjukkan dalam pertanyaan Anda, pengujian untuk kesetaraan pada variabel float tidak dapat diandalkan.
Hal yang sama berlaku untuk
<=
dan>=
.Namun, tidak ada masalah keandalan seperti itu untuk tipe integer. Menurut pendapat saya, penulis mengungkapkan dirinya pendapat untuk yang lebih mudah dibaca.
Apakah Anda setuju atau tidak dengannya, tentu saja merupakan pendapat Anda .
sumber
<
atau<=
berdasarkan pada apa yang paling alami untuk masalah khusus yang saya selesaikan. Seperti yang telah ditunjukkan orang lain, dalam loop UNTUK<
lebih masuk akal dalam bahasa tipe-C. Ada kasus penggunaan lain yang mendukung<=
. Gunakan semua alat yang Anda inginkan, kapan dan di mana sesuai.for (unsigned int i = n; i >= 0; i--)
ataufor (unsigned int i = x; i <= y; i++)
jikay
terjadi menjadiUINT_MAX
. Ups, loop itu selamanya.Setiap hubungan
<
,<=
,>=
,>
dan juga==
dan!=
memiliki mereka gunakan-kasus untuk membandingkan dua nilai floating-point. Masing-masing memiliki makna spesifik dan yang sesuai harus dipilih.Saya akan memberikan contoh untuk kasus di mana Anda ingin operator ini untuk masing-masingnya. (Namun, waspadai NaNs.)
f
yang menggunakan nilai titik-mengambang sebagai input. Dalam rangka untuk mempercepat perhitungan Anda, Anda memutuskan untuk menambahkan cache dari nilai yang paling baru-baru dihitung, yaitu, pemetaan tabelx
untukf(x)
. Anda benar-benar ingin menggunakan==
untuk membandingkan argumen.x
? Anda mungkin ingin menggunakannyax != 0.0
.x
berada dalam interval satuan?(x >= 0.0) && (x < 1.0)
adalah kondisi yang benar.d
suatu matriks dan ingin memberi tahu apakah itu pasti positif? Tidak ada alasan untuk menggunakan hal lain selaind > 0.0
.alpha <= 1.0
.Matematika floating-point (secara umum) tidak tepat. Tetapi itu tidak berarti bahwa Anda harus takut, memperlakukannya sebagai sihir, dan tentu saja tidak selalu memperlakukan dua jumlah titik-mengambang sama jika mereka berada di dalam
1.0E-10
. Melakukan hal ini akan benar-benar mematahkan matematika dan menyebabkan semua hal-hal aneh terjadi.x != 0.0
dany
merupakan nilai floating-point yang terbatas,y / x
tidak perlu terbatas. Tetapi mungkin relevan untuk mengetahui apakahy / x
tidak terbatas karena melimpah atau karena operasi tidak secara matematis didefinisikan dengan baik untuk memulai.x
harus berada dalam interval unit [0, 1), saya akan benar-benar kesal jika ia mengeluarkan kegagalan pernyataan ketika dipanggil denganx == 0.0
ataux == 1.0 - 1.0E-14
.1.0E-30
, tidak ada yang diperoleh. Yang Anda lakukan hanyalah meningkatkan kemungkinan memberikan jawaban yang salah.alpha
mungkin dipengaruhi oleh kesalahan pembulatan dan oleh karena itualpha <= 1.0
mungkin benar meskipun nilai matematika sebenarnya untuk ekspresialpha
dihitung dari mungkin benar-benar lebih besar dari 1. Tapi tidak ada yang bisa Anda lakukan tentang hal itu pada saat ini.Seperti biasa dalam rekayasa perangkat lunak, menangani kesalahan pada tingkat yang sesuai dan menanganinya hanya sekali. Jika Anda menambahkan kesalahan pembulatan pada urutan
1.0E-10
(ini tampaknya merupakan nilai ajaib yang digunakan kebanyakan orang, saya tidak tahu mengapa) setiap kali Anda membandingkan jumlah titik-mengambang, Anda akan segera melakukan kesalahan pada urutan1.0E+10
...sumber
Jenis kondisional yang digunakan dalam satu lingkaran dapat membatasi jenis optimisasi yang dapat dilakukan oleh kompiler, baik atau buruk. Misalnya, diberikan:
kompilator dapat berasumsi bahwa kondisi di atas harus menyebabkan loop untuk keluar setelah loop ke-n kecuali kecuali n 65535 dan loop mungkin keluar dalam beberapa cara selain oleh i melebihi n. Jika ketentuan tersebut berlaku, kompiler harus membuat kode yang akan menyebabkan loop dijalankan hingga sesuatu selain kondisi di atas menyebabkannya keluar.
Jika lingkaran itu malah ditulis sebagai:
maka kompiler dapat dengan aman mengasumsikan bahwa loop tidak akan pernah perlu mengeksekusi lebih dari n kali dan dengan demikian dapat menghasilkan kode yang lebih efisien.
Perhatikan bahwa setiap luapan dengan tipe yang ditandatangani dapat memiliki konsekuensi buruk. Diberikan:
Kompiler mungkin menulis ulang itu sebagai:
Perulangan seperti itu akan berperilaku identik dengan yang asli jika tidak ada overflow yang terjadi dalam perhitungan, tetapi dapat berjalan selamanya bahkan pada platform perangkat keras di mana integer overflow biasanya memiliki semantik pembungkus yang konsisten.
sumber