2014-05-20 42 views
4

香港專業教育學院碰到過這樣的代碼PHP的字符串比較,爲什麼投浮

<?php 

$a = md5('240610708'); 
$b = md5('QNKCDZO'); 

echo "$a\n"; 
echo "$b\n"; 
echo "\n"; 
var_dump($a); 
var_dump($b); 
var_dump($a == $b); 

這種評價爲2串這可能是一個數量0exxxxxx。據我所知,如果任一被在一個數字語境中,則字符串將被當字符串在數值上下文被評估爲經採取爲數字,通過http://www.php.net/manual/en/language.types.string.php#language.types.string.conversion

證實,所得到的值 和類型被確定爲如下。

如果字符串不包含任何字符「」,‘E’,或‘E’ 和數值裝配到整數類型的限制(如通過 PHP_INT_MAX定義)時,字符串將被評估爲一個整數。在所有其他 的情況下,它將被評估爲浮動。

該值由字符串的起始部分給出。如果字符串 以有效數字數據開頭,則這將是使用的值。 否則,該值將爲0(零)。有效的數字數據是一個可選符號 ,後跟一個或多個數字(可選包含小數點 ),後跟可選的指數。指數是 'e'或'E'後跟一個或多個數字。

我只是不確定爲什麼==當雙方都是字符串類型時觸發數值比較。

+1

@Hanky웃Panky在意識到'==='但是當雙方都是字符串時,什麼導致雙方被當作浮動。我知道這發生在有多種類型時 – exussum

回答

5

TL; DR

這是PHP中字符串「智能」比較的結果。是的,這不是你所期待的,但現在 - 它是如何實現的。

進一步挖掘

維護比較

爲了實現原因,你需要尋找到PHP源(更大的好或壞)。在PHP中,有用於處理比較的compare_function等。它包含不同類型參數的不同情況。因此,對於字符串,它是:

case TYPE_PAIR(IS_STRING, IS_STRING): 
    zendi_smart_strcmp(result, op1, op2); 
    return SUCCESS; 

TYPE_PAIR,因爲任何其他的東西,僅僅是一個宏。

移動更深

從前面的步驟,我們現在正在zendi_smart_strcmp。比較兩個字符串是PHP的「聰明之事」。在這裏,我們有:

if ((ret1=is_numeric_string_ex(Z_STRVAL_P(s1), Z_STRLEN_P(s1), &lval1, &dval1, 0, &oflow1)) && (ret2=is_numeric_string_ex(Z_STRVAL_P(s2), Z_STRLEN_P(s2), &lval2, &dval2, 0, &oflow2))) 
{ 
    //compare as two numbers, I've omitted this 
} 
else 
{ 
    string_cmp: //yes, yes, we're using goto 
    Z_LVAL_P(result) = zend_binary_zval_strcmp(s1, s2); 
    ZVAL_LONG(result, ZEND_NORMALIZE_BOOL(Z_LVAL_P(result))); 
} 

裏面省略碼也有用於確定結果是longdouble部分 - 但是這無關緊要,因爲我們已經知道是什麼引起的比較,因爲花車:只要字符串可以治療數字,PHP將用它來產生比較 - 和 - 是的,這旨在(所以,是的,串"1000"等於"1e3"使用==運營商,同爲"255""0xFF"時 - 它們不包含「 e「(指數)部分,但仍然是等於

解決方案

您可以限制用的情況下,例如:

var_dump("0e8" == "0e6"); //true 

所以沒必要處理MD5哈希值。如果將其與數字進行比較,則爲真(因爲兩個操作數都是有效的浮點數,並且0 x 10^8 == 0 x 10^6)。但它們與絃樂不一樣。因此,你的直接的解決辦法是 - 用===符來比較:

var_dump("0e8" === "0e6"); //false 

是的,這是在PHP中令人困惑的事情 - 因爲它並不明顯(和有爭議至少)。但這就是目前的工作原理。