PHP max() 和 min() 不同类型的奇怪行为

PHP max() and min() weird behavior with different types

过去两个小时我一直在为这种行为挠头:

echo 'max(1, "a", "2"   ) : '; var_dump( max( 1, 'a', '2' ) );
echo 'max(1, "2", "a"   ) : '; var_dump( max( 1, '2', 'a' ) );
echo 'max(   "a", "2", 1) : '; var_dump( max( 'a', '2', 1 ) );
echo 'max(   "2", "a", 1) : '; var_dump( max( '2', 'a', 1 ) );
echo "\n";
echo 'min(1, "a", "2"   ) : '; var_dump( min( 1, 'a', '2' ) );
echo 'min(1, "2", "a"   ) : '; var_dump( min( 1, '2', 'a' ) );
echo 'min(   "a", "2", 1) : '; var_dump( min( 'a', '2', 1 ) );
echo 'min(   "2", "a", 1) : '; var_dump( min( '2', 'a', 1 ) );

打印出:

max(1, "a", "2"   ) : string(1) "2"
max(1, "2", "a"   ) : string(1) "a"
max(   "a", "2", 1) : int(1)
max(   "2", "a", 1) : int(1)

min(1, "a", "2"   ) : string(1) "2"
min(1, "2", "a"   ) : string(1) "a"
min(   "a", "2", 1) : int(1)
min(   "2", "a", 1) : int(1)

当我期待时:

max(1, "a", "2"   ) : string(1) "2"
max(1, "2", "a"   ) : string(1) "2"
max(   "a", "2", 1) : string(1) "2"
max(   "2", "a", 1) : string(1) "2"

min(1, "a", "2"   ) : string(1) "a"
min(1, "2", "a"   ) : string(1) "a"
min(   "a", "2", 1) : string(1) "a"
min(   "2", "a", 1) : string(1) "a"

请注意,max()min() 函数的值始终相同,但顺序不同。

此外,根据文档,与整数相比,不是以数字字符开头的字符串被评估为整数 0,但多个字符串值按字母数字进行比较。资料来源:

如何解释这个输出?

min() and max()中的比较是按顺序进行的,如源代码所示:

min() source code:

//...
min = &args[0];

for (i = 1; i < argc; i++) {
    is_smaller_function(&result, &args[i], min);
    if (Z_TYPE(result) == IS_TRUE) {
        min = &args[i];
    }
}
//...

max() source code:

//...
max = &args[0];

for (i = 1; i < argc; i++) {
    is_smaller_or_equal_function(&result, &args[i], max);
    if (Z_TYPE(result) == IS_FALSE) {
        max = &args[i];
    }
}
//...

因此您可以看到该函数遍历数组并检查下一个值是否 smaller/bigger 比前一个 smallest/biggest 保存的值。


要了解如何获得这些结果,您还必须知道值的比较是在 PHP type juggling.

之后完成的

那么让我们看两个例子来了解这些函数是如何工作的:

示例 1

max ( 1 , 'a' , '2' )
      │    │     │
      1 > 'a'    │
        │        │
        1    <  '2'
             │
             └ Result: '2'
  1. 比较1'a',数字上下文意味着'a'转换为01大于0.
    → int 1 返回

  2. 比较1'2',数字字符串表示'2'转换为22大于1.
    → 返回字符串'2'

  • 结果:字符串'2'

示例 2

max ( 1 , '2' , 'a' )
      │    │     │
      1 < '2'    │
        │        │
       '2'   <  'a'
             │
             └ Result: 'a'
  1. 比较1'2',数字字符串表示'2'转换为22大于1.
    → 返回字符串'2'

  2. Comparing '2' and 'a',两个字符串都是字符串比较的意思,'a'大于'2'只是比较了ASCII values.
    → 返回字符串'a'

  • 结果:字符串'a'

同样的规则适用于所有其他示例。