PHP terkenal dengan tipenya yang juggling. Saya harus mengakuinya membuat saya bingung, dan saya mengalami kesulitan untuk menemukan hal-hal dasar logis / fundamental dalam perbandingan.
Sebagai contoh: Jika $a > $b
benar dan $b > $c
benar, harus itu berarti bahwa $a > $c
adalah selalu benar juga?
Mengikuti logika dasar, saya akan mengatakan ya namun saya bingung, saya tidak terlalu mempercayai PHP dalam hal ini. Mungkin seseorang dapat memberikan contoh dimana hal ini tidak terjadi?
Juga saya bertanya-tanya dengan operator yang ketat lebih rendah dari dan lebih ketat daripada (karena artinya dijelaskan secara ketat yang hanya saya ketahui di masa lalu dari perbandingan kesetaraan) jika ada bedanya jika operan kiri dan kanan ditukar dengan nilai yang sangat tidak sama:
# Precondition:
if ($a === $b) {
throw new Exception(
'Both are strictly equal - can not compare strictly for greater or smaller'
);
}
($a > $b) !== ($b > $a)
Untuk sebagian besar dari semua kombinasi perbandingan jenis, operator perbandingan yang lebih besar / lebih kecil ini tidak didokumentasikan, jadi membaca manual tidak terlalu membantu dalam kasus ini.
sumber
($a > $b) !== ($b < $a)
?Jawaban:
Operator perbandingan PHP menyimpang dari definisi ilmiah komputer dalam beberapa cara:
Untuk membentuk suatu hubungan ekivalensi
==
harus refleksif, simetris dan transitif:PHP
==
operator adalah tidak refleksif , yaitu$a == $a
tidak selalu benar:Catatan: Fakta yang melibatkan perbandingan
NAN
selalufalse
tidak spesifik untuk PHP. Ini diamanatkan oleh IEEE 754 Standard for Floating-Point Arithmetic ( info lebih lanjut ).PHP
==
operator adalah simetris , yaitu$a == $b
dan$b == $a
selalu sama.Operator PHP tidak
==
bersifat transitif , yaitu dari$a == $b
dan$b == $c
tidak tidak berikut$a == $c
:Untuk merupakan a tatanan parsial
<=
/>=
harus refleksif, anti-simetris dan transitif:PHP
<=
operator adalah tidak refleksif , yaitu$a <= $a
tidak selalu benar (Contoh sama seperti untuk==
).PHP
<=
operator adalah tidak anti-simetris , yaitu dari$a <= $b
dan$b <= $a
tidak mengikuti$a == $b
:PHP
<=
operator tidak transitif , yaitu dari$a <= $b
dan$b <= $c
tidak mengikuti$a <= $c
(Contoh sama seperti untuk==
).Ekstra: PHP
<=
operator adalah tidak keseluruhan , yaitu baik$a <= $b
dan$b <= $a
dapat palsu:Untuk merupakan a tatanan parsial yang ketat
<
/>
harus tidak refleksif, asimetris, dan transitif:Operator PHP
<
tidak refleksif , artinya$a < $a
tidak pernah benar. Perhatikan bahwa ini benar hanya pada PHP 5.4 . SebelumnyaINF < INF
dievaluasi ketrue
.PHP
<
operator adalah tidak asimetris , yaitu dari$a < $b
tidak mengikuti!($b < $a)
(Contoh sama seperti untuk<=
tidak menjadi anti-simetris).PHP
<
operator adalah tidak transitif , yaitu dari$a < $b
dan$b < $c
tidak mengikuti$a < $c
:Ekstra: Operator PHP
<
adalah tidak trikotomi , yaitu semua$a < $b
,$b < $a
dan$a == $b
bisa salah (Contoh sama dengan<=
tidak total).Ekstra: Operator PHP
<
bisa melingkar , yaitu mungkin saja$a < $b
,$b < $c
dan$c < $a
:Catatan: Contoh di atas menampilkan pemberitahuan "Objek kelas stdClass tidak bisa diubah menjadi ganda".
Anda dapat menemukan beberapa grafik yang bagus untuk operator perbandingan PHP di PHP Sadness 52 - Operator perbandingan .
Sebagai catatan terakhir, saya ingin menunjukkan bahwa ada dua persamaan yang dijamin oleh PHP (tidak seperti yang lainnya). Keduanya selalu berlaku, hanya karena kompiler mengurangi satu sama lain:
sumber
($a > $b) and ($b > $c)
dengan$a > $c
meskipun dokumentasinya mengatakan bahwa<
/>
operator mengatakan mereka ketat ?$a == $b
itu sama dengan(type) $a === (type) $b
. Contoh sederhananya adalah itu"15" == "0xf"
, tetapi(int) "15" !== (int) "0xf"
. Dan perbandingan dan aturan casting di PHP benar-benar gila ^^(int)"0xf"
mengevaluasi ke integer0
, jadi tentu saja0 !== 15
. Perbandingan dalam contoh ini berperilaku persis seperti yang diharapkan. Pengecoranlah yang membingungkan di sini. Saya akui,(INF < INF) === true
ini adalah masalah perbandingan yang asli, tetapi ini adalah kasus khusus, dan telah diselesaikan seperti yang Anda tunjukkan. Jawaban yang bagus .. +1Tidak ada operator perbandingan identik yang ketat (
>==
atau<==
) di PHP (setidaknya dengan PHP 5.6.14) , tetapi ada beberapa cara untuk menerapkan pemeriksaan tipe yang ketat sebelum memeriksa Greater / Lower:if (gettype($a) === gettype($b))
if ((string)$a === (string)$b)
if (($a . '') === ($b . ''))
Perhatikan bahwa:
INF
danNAN
tipe difloat
bawahieee754e
selalu bertipefloat
, dan tidak pernahinteger
sekalipun jumlahnya kecilPHP_INT_MAX
otomatis dikonversi kefloat
INF
nilainyaNULL
0
dikonversi dari oktal ke desimal (menurut konvensi)0
ke integer strip di depan0
Daftar beberapa perbandingan eksotis:
Sama tapi tidak identik:
Lebih Rendah dan Lebih Besar pada saat bersamaan?
Sama DAN identik:
Lebih Rendah atau Lebih Besar:
$a > $b > $c
Teka-teki ketika:$a
tidak lebih dari$c
.Perbandingan senar menyenangkan: 'Queen'
>
'King'>
'Jack'>
'Ace'Lihat juga tabel perbandingan tipe PHP yang mencakup pasangan:
isset()
danis_null()
if()
danempty()
==
vs.===
Periksa perbedaan antara versi PHP langsung di. http://3v4l.org/MAfDu .
sumber
if ( (string)$a===(string)$b )
tetapi bukankah ini persis samaif ( (string)$a==(string)$b )
?(string)1==(string)'01'
->bool(true)
dan untuk tipe-juggle(1 . '')=='01'
->bool(true)
tidak persis sama seperti===
saat Anda masukbool(false)
ke kedua akunINFINITY is equal to INFINITY which is mathematically incorrect!
adalah pernyataan yang bisa diperdebatkan. Juga perhatikan bahwaNaN
menurut konvensi tidak lebih dari, kurang dari atau sama dengan apa pun dalam bahasa pemrograman apa pun yang saya ketahui.Setelah Anda mengoreksi bagian kedua dari pertanyaan Anda, saya serahkan jawaban untuk bagian itu kepada yang lain. Saya hanya ingin memberikan jawaban yang paling mengejutkan untuk bagian pertama pertanyaan Anda, yaitu apakah ada contoh dari
<
dan>
operator yang intransitif. Ini dia.Ini semua adalah
true
:Jika
<
transitif ($a < $b
∧$b < $c
⇒$a < $c
), baris terakhir adalahtetapi PHP mencoba untuk menjadi baik (?!) dan menafsirkan string sebagai angka kapanpun itu bisa.
Ternyata, karena intransitivitas di atas,
sort()
dapat mengurutkan elemen yang sama ke dalam urutan yang berbeda tergantung pada urutan masukannya, bahkan jika tidak ada dua elemen==
(dan tidak ada elemen yang NAN). Saya menunjukkan ini dalam komentar ke sort () , yang intinya adalah:sumber
sort()
tabel baru yang bagus , pilih juga untuk implikasi praktis saat menulis posting blog terkait Nilai PHP Terbesar . Terima kasih sekali lagi atas jawaban Anda.usort
jika memungkinkan?usort($arr, 'strcmp')
. Ini berfungsi (untuk string, tentu saja), tetapi paling baik digunakansort($arr, SORT_STRING)
.