PHP 0 को एक स्ट्रिंग के बराबर क्यों मानता है?


111

मेरे पास निम्नलिखित कोड है:

$item['price'] = 0;
/* Code to get item information goes in here */
if($item['price'] == 'e') {
    $item['price'] = -1;
}

इसका उद्देश्य आइटम की कीमत को 0 पर प्रारंभ करना है और फिर इसके बारे में जानकारी प्राप्त करना है। यदि मूल्य को 'ई' के रूप में सूचित किया जाता है, तो इसका मतलब है कि बिक्री के बजाय एक एक्सचेंज, जो डेटाबेस में एक नकारात्मक संख्या के रूप में संग्रहीत है।

मूल्य को 0 के रूप में छोड़ने की संभावना भी है, या तो क्योंकि आइटम एक बोनस है या क्योंकि कीमत बाद के क्षण में सेट की जाएगी।

लेकिन, जब भी मूल्य निर्धारित नहीं किया जाता है, जो इसे 0 के प्रारंभिक मूल्य के साथ छोड़ देता है, तो ifऊपर दिए गए लूप सही के रूप में मूल्यांकन करता है और मूल्य -1 पर सेट होता है। अर्थात्, यह 0 को 'ई' के बराबर मानता है।

इसे कैसे समझाया जा सकता है?

जब मूल्य 0 (आरंभीकरण के बाद) के रूप में प्रदान किया जाता है, तो व्यवहार अनियमित होता है: कभी-कभी यदि यह सच के रूप में मूल्यांकन करता है, तो कभी-कभी यह गलत के रूप में मूल्यांकन करता है। *


1
मैंने पाया कि डबल == के बजाय ट्रिपल === का उपयोग करना अपेक्षित व्यवहार देता है। लेकिन यह अभी भी अजीब है।
सेरियो डोमिंगल्स

2
(संदर्भ) अध्याय प्रकार के करतब में PHP मैनुअल में पर्याप्त रूप से समझाया गया है और टाइप तुलना तालिका
गॉर्डन

1
यदि एकमात्र संभव स्ट्रिंग प्रकार 'ई' है, तो क्या आप सिर्फ is_string ($ आइटम ["मूल्य"]) की जांच नहीं कर सकते? यह === से थोड़ा अधिक कुशल होगा। [उद्धरण वांछित]
जिमी लिन

में कमजोर तुलना स्ट्रिंग के बीच और पूर्णांक स्ट्रिंग पूर्णांक में बदल जाती है (बजाय पूर्णांक स्ट्रिंग के लिए "पदोन्नत" जा रहा है)। if((string)$item['price'] == 'e')अजीब व्यवहार को ठीक करता है। अधिक जानकारी के लिए stackoverflow.com/a/48912540/1579327 देखें
पाओलो

कृपया नीचे दिए गए टिप्पणियों में एक अन्य मामले पर ध्यान दें, जहां 0 (पूर्णांक) डबल स्ट्रिंग ऑपरेटर का उपयोग करते समय किसी अन्य स्ट्रिंग के बराबर होता है।
हैथम स्वीमिलम

जवाबों:


113

आप कर रहे हैं ==जो आपके लिए प्रकारों को अलग करता है।

0एक इंट है, इसलिए इस मामले में यह 'e'एक इंट में डालने जा रहा है । जो एक के रूप में पार्स करने योग्य नहीं है और बन जाएगा 0। एक स्ट्रिंग '0e'बन जाएगा 0और मैच होगा!

उपयोग ===


14
शिथिल तुलना का एक और नुकसान।
एमसी सम्राट

5
मुश्किल एक। बस इस एक में टकरा गया और चकित था कि क्यों स्ट्रिंग == 0. यह याद रखना चाहिए।
ग्रेजगोरज

2
जब मैं स्ट्रिंग कीज़ पर लूपिंग कर रहा था, तब भी इस पर अपना सिर खुजला रहा था, लेकिन सरणी में एक प्रारंभिक 'शून्य' इंडेक्स आइटम था, जो पहले स्ट्रिंग की तुलना में सही था। मैं क्या था? कैसे में ... तो, यकीन है कि पर्याप्त, इस जवाब को मंजूरी दे दी है कि! मुझे आश्चर्य है कि इस पूरे प्रश्न का उत्तर किसी ने स्वीकार नहीं किया है। बस कुछ सवाल पूछने के लिए जाता है पूछने वाले झटके हैं।
अतुल्य

48

यह इस कारण से है कि ==तुलना ऑपरेटर किस तरह से PHP ऑपरेशन करता है:

यदि आप किसी संख्या की स्ट्रिंग के साथ तुलना करते हैं या तुलना में संख्यात्मक तार शामिल होते हैं, तो प्रत्येक स्ट्रिंग को एक संख्या में बदल दिया जाता है और तुलनात्मक रूप से प्रदर्शन किया जाता है। […] प्रकार रूपांतरण तब नहीं होता है जब तुलना होती है ===या !==इसमें प्रकार के साथ-साथ मूल्य की तुलना करना शामिल होता है।

जैसा कि पहला ऑपरेंड एक संख्या है ( 0) और दूसरा एक स्ट्रिंग ( 'e') है, स्ट्रिंग को भी एक संख्या में परिवर्तित किया जाता है ( विभिन्न प्रकारों के साथ तालिका तुलना भी देखें )। स्ट्रिंग डेटा प्रकार पर मैनुअल पेज परिभाषित करता है कि स्ट्रिंग को संख्या रूपांतरण कैसे किया जाता है:

जब किसी स्ट्रिंग का संख्यात्मक संदर्भ में मूल्यांकन किया जाता है, तो परिणामी मान और प्रकार निम्नानुसार निर्धारित किया जाता है।

यदि स्ट्रिंग में कोई भी वर्ण ' .', ' e', या ' E' नहीं है और संख्यात्मक मान पूर्णांक प्रकार की सीमाओं में फिट बैठता है (जैसा कि परिभाषित किया गया है PHP_INT_MAX), स्ट्रिंग का पूर्णांक के रूप में मूल्यांकन किया जाएगा। अन्य सभी मामलों में इसका मूल्यांकन फ्लोट के रूप में किया जाएगा।

इस स्थिति में स्ट्रिंग है 'e'और इस प्रकार इसका मूल्यांकन फ्लोट के रूप में किया जाएगा:

मान स्ट्रिंग के प्रारंभिक भाग द्वारा दिया गया है। यदि स्ट्रिंग मान्य संख्यात्मक डेटा से शुरू होती है, तो यह उपयोग किया जाने वाला मान होगा। अन्यथा, मान 0(शून्य) होगा। वैध संख्यात्मक डेटा एक वैकल्पिक संकेत है, जिसके बाद एक या एक से अधिक अंक (वैकल्पिक रूप से एक दशमलव बिंदु होता है), इसके बाद एक वैकल्पिक प्रतिपादक होता है। घातांक एक ' e' या ' E' है जिसके बाद एक या अधिक अंक होते हैं।

जैसा कि 'e'एक वैध संख्यात्मक डेटा से शुरू नहीं होता है, यह फ्लोट का मूल्यांकन करता है 0


3
php आसानी से तुलनीय होने के लिए सबसे अधिक सब कुछ डिजाइन करता है और फिर हमारे दिन को बर्बाद करने के लिए कुछ गोच में फेंकता है। यह PHP के बाकी डिज़ाइन दर्शन के साथ फिट नहीं है। जब तक धोखे में दर्शन नहीं है ???
user3338098

1
विशेष रूप से "ई" के बाद से सच और "" से झूठे कास्ट करता है
user3338098

20
"ABC" == 0

मूल्यांकन करता है trueक्योंकि पहले "ABC" पूर्णांक में परिवर्तित होता है और 0 फिर इसकी तुलना की जाती है 0

यह PHP भाषा का एक अजीब व्यवहार है: आम तौर पर किसी को परिणाम के साथ 0स्ट्रिंग "0"और फिर पदोन्नति की उम्मीद की जाएगी । शायद यही कारण है कि जावास्क्रिप्ट जैसी अन्य भाषाओं में जहां कमजोर तुलना का मूल्यांकन होता है ।"ABC"false"ABC" == 0false

एक सख्त तुलना करने से समस्या हल होती है:

"ABC" === 0

मूल्यांकन करता है false

लेकिन क्या होगा अगर मुझे संख्याओं की तुलना संख्याओं के साथ करने की आवश्यकता है?

"123" === 123

मूल्यांकन करता है falseक्योंकि बाएं और दाएं शब्द अलग-अलग प्रकार के हैं।

क्या वास्तव में जरूरत है PHP प्रकार की बाजीगरी के नुकसान के बिना एक कमजोर तुलना है।

समाधान शर्तों को स्पष्ट रूप से स्ट्रिंग को बढ़ावा देना है और फिर एक तुलना करना है (सख्त या कमजोर अब कोई फर्क नहीं पड़ता)।

(string)"123" === (string)123

है

true

जबकि

(string)"123" === (string)0

है

false


मूल कोड के लिए लागू:

$item['price'] = 0;
/*code to get item information goes in here*/
if((string)$item['price'] == 'e') {
    $item['price'] = -1;
}

9

== ऑपरेटर विभिन्न प्रकारों के होते हुए भी मूल्यों से मेल खाने की कोशिश करेगा। उदाहरण के लिए:

'0' == 0 will be true

यदि आपको टाइप तुलना की आवश्यकता है, तो === ऑपरेटर का उपयोग करें:

'0' === 0 will be false

9

आपकी समस्या दोहरा समान ऑपरेटर है, जो दाएं सदस्य को बाईं ओर के प्रकार को टाइप करेगा। यदि आप पसंद करते हैं तो सख्त का उपयोग करें।

if($item['price'] == 'e') {
    $item['price'] = -1;
}

आइए अपने कोड पर वापस जाएं (ऊपर प्रतिलिपि बनाई गई)। इस मामले में, ज्यादातर मामलों में, $ आइटम ['मूल्य'] एक पूर्णांक है (सिवाय इसके कि जब यह ई के बराबर है, जाहिर है)। जैसे, PHP के नियमों के अनुसार, PHP "e"पूर्णांक को टाइपकास्ट करेगा , जो पैदावार देता है int(0)। (मेरा विश्वास मत करो? <?php $i="e"; echo (int)$i; ?>)।

इससे आसानी से दूर होने के लिए, ट्रिपल बराबर (सटीक तुलना) ऑपरेटर का उपयोग करें, जो प्रकार की जांच करेगा और अंतर्निहित टाइपकास्ट नहीं करेगा।

पुनश्च: एक PHP मजेदार तथ्य: a == bइसका मतलब यह नहीं है b == a। अपना उदाहरण लें और इसे उल्टा करें: if ("e" == $item['price'])वास्तव में कभी पूरा नहीं होगा बशर्ते कि $ आइटम ['मूल्य'] हमेशा पूर्णांक हो।


7

PHP में "0", "गलत", "ऑफ" के रूप में == असत्य और "1", "ऑन", "सत्य" के रूप में == सच के मिश्रण को मान्य करने के लिए एक आसान तरीका है, जिसे अक्सर अनदेखा किया जाता है। GET / POST तर्कों को पार्स करने के लिए यह विशेष रूप से उपयोगी है:

filter_var( $item['price'], FILTER_VALIDATE_BOOLEAN );

यह इस उपयोग-मामले के लिए पूर्ण रूप से प्रासंगिक नहीं है, लेकिन समानता और तथ्य को देखते हुए यह परिणाम खोज है, जब यह पता चलता है कि मान्य (स्ट्रिंग) "0" के प्रश्न को गलत बताते हुए मुझे लगता है कि यह दूसरों की मदद करेगा।

http://www.php.net/manual/en/filter.filters.validate.php


6

आपको ===इसके बजाय उपयोग करना चाहिए ==, क्योंकि साधारण ऑपरेटर प्रकारों की तुलना नहीं करता है। इसके बजाय यह वस्तुओं को टाइपकास्ट करने का प्रयास करेगा।

इस बीच ===आइटम के प्रकार पर विचार करता है।

  • === "बराबर" का अर्थ है,
  • == इसका मतलब "ईहेह .. थोड़े लगता है"

1
समझा। अब यह काम करता है (एक टाइपकास्ट के साथ):if((string)$item['price']=='e'){ $item['price'] = -1; }
सेरियो डोमिंगेज

लेकिन आपको ऐसा नहीं करना चाहिए। बस ===ऑपरेटर का उपयोग करें
tereško

3

मुझे लगता है कि मैंने एक ही अजीब व्यवहार में भागते हुए, उदाहरणों के द्वारा दिखाना सबसे अच्छा है। मेरा परीक्षण मामला देखें और उम्मीद है कि यह व्यवहार को बेहतर ढंग से समझने में आपकी मदद करेगा:

// Normal comparison using the == Operator
echo (0 == "0"); // true
echo (0 == "a"); // true
echo (0 == "safta!"); // true
echo (1000 == "bla"); // false. It appears that PHP has a weird behavior only with the number / string 0 / "0" according to the past 3 examples.
echo (23 == "23"); // true. So as we said, PHP has a problem (not a problem but weird behavior) only when the number / string 0 (or "0") is present
echo (23 == "24"); // false. values aren't equal (unlike last example). The type is less relevant with the == operator as we can see.

// Now using the === and !== Operators
echo ("0" === 0); // false, since === requires both value and type to be the same. Here, type is different (int vs string)
echo ("0" !== 0); // true because they aren't the same in terms of === comparison (type is different and that's why it's true)
echo ("bla" === "blaa"); // false because the values are not the same. The type is the same, but === checks for both equal type and equal value.

//Now using casting and === Operator:
echo ((string)123 === "123"); // true. The casting of the int 123 to string changed it to "123" and now both variables have same value and are of same type
echo ((int)"123" === 123); // true. The casting of the string 123 to int, changed it to int, and now both variables are of same value and type (which is exactly what the === operator is looking for)

// Now using casting and == Operator. Basically, as we've seen above, the == care less for the
// type of var, but more to the value. So the casting is less relevant here, because even
// without casting, like we saw earlier, we can still compare string to int with the == operator
// and if their value is same, we'll get true. Either way, we will show that:
echo ((string)123 == "123"); // true. The casting of the int 123 to string changed it to "123" and now both vars have same value and are of same type
echo ((int)"123" == 123); // true. The casting of the string 123 to int, changed it to int, and now both vars are of same value and type (which is exactly what the === operator is looking for)

महान परीक्षण, मैंने वैसा ही किया लेकिन मैंने एक अच्छी तालिका बनाई। मेरा जवाब देखें
IAMTHEBEST

हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.