使用PHP位运算判断两个数字是否为同符号

452 阅读3分钟

本文已参与「新人创作礼」活动,一起开启掘金创作之路。

一、问题描述

问题:写一个函数,,在不直接使用比较运算符或与0比较的前提下,判断给定的两个数字是否是符号相同的。

例如 is_same_symbol(-1, 10) == false; is_same_symbol(10,20)=true; is_same_symbol(-1,-10)=true; 同时,规定0属于正数。

二、解决问题

在二进制表示中,最高位是1的话,就是负数。最高位为0则为正数。因此我可以想办法通过位运算来判断。1^0 = 1。所以 负数^正数=负数。其实就是类似于乘法了。

1、位运算符

位运算符允许对整型数中指定的位进行求值和操作。

例子名称结果
$a & $bAnd(按位与)将把 $a 和 $b 中都为 1 的位设为 1。
$a | $bOr(按位或)将把 $a 和 $b 中任何一个为 1 的位设为 1。
$a ^ $bXor(按位异或)将把 $a 和 $b 中一个为 1 另一个为 0 的位设为 1。
~ $aNot(按位取反)将 $a 中为 0 的位设为 1,反之亦然。
$a << $bShift left(左移)将 $a 中的位向左移动 $b 次(每一次移动都表示“乘以 2”)。
$a >> $bShift right(右移)将 $a 中的位向右移动 $b 次(每一次移动都表示“除以 2”)。

位移在 PHP 中是数学运算。向任何方向移出去的位都被丢弃。左移时右侧以零填充,符号位被移走意味着正负号不被保留。右移时左侧以符号位填充,意味着正负号被保留。

要用括号确保想要的优先级。例如 $a & $b == true 先进行比较再进行按位与;而 ($a & $b) == true 则先进行按位与再进行比较。

如果 &、 | 和 ^ 运算符的左右两个操作对象都是字符串,将对会组成字符串的字符 ASCII 值执行操作,结果也是一个字符串。除此之外,两个操作对象都将 转换为整数 ,结果也将会是整数。

如果 ~ 运算符的操作对象是字符串,则将对组成字符串的字符 ASCII 值进行操作, 结果将会是字符串,否则操作对象和结构都会是整数。

<< 和 >> 运算符的操作对象和结果始终都是整数。

2、方法封装

确定可以使用位运算 ^来处理 ,那么封装函数如下:

function is_same_symbol($a,$b){
	return (($a ^ $b) > 0);
}

$a=12;
$b=-10;

if (is_same_symbol($a, $b) == true){
    printf ("same symbol");
}else{
    printf ("not same symbol");
}
  • 上面的例子会输出:not same symbol

这里用到了比较运算符(^)。其实完全可以再简化一下,把函数中 >0 的判断比较去掉,因为我们只需要知道第一位符号位即可。


function is_same_symbol($a,$b){
	return !(($a ^ $b) >> 31);
}

右移31位,则只剩下最高位符号位,不是0,就是1。

另外,如果处理非数字型,而是字符串型的数字,如 $a="100.01",$b="-10.01",只需转化成数字型即可。

【注意】在使用位运算的时候注意运算优先级。



END


如有问题请在下方留言。

或关注我的公众号“孙三苗”(sunsanmiao),输入“联系方式”。获得进一步帮助。