PHP 使用位运算实现四则运算的代码

计算机最基本的操作单元是字节,一个字节由8个位组成,一个位只能存储一个0或1。所有数据在计算机中都是采用二进制,即 1 和 0 的编码存储和运算。

这次尝试在 PHP 中使用位运算实现四则运算,首先介绍一些基本概念:

原码:将最高位作为符号位(0表示正,1表示负),其它数字位代表数值本身的绝对值

反码:正数反码和原码一样;如果是负数,符号位不变,其余各位取反

补码:正数补码和原码一样;负数补码为反码加 1

计算机中的数使用 补码  的形式存储

⒈ 加法

二进制中只有 0 和 1,0 + 0、0 + 1 都不需要进位,但 1 + 1 则需要进位。所以,首先通过 抑或 运算得到不需要进位的那些位相加的结果。然后进行 与 运算,当相加的两位都为 1 时结果为 1。所以如果与运算的结果大于 0 说明需要进位,此时将与运算的结果按位左移 1 位,此时将左移的结果与抑或运算得到的结果重新进行上述的运算过程,直到与运算的结果为 0。

<?php
  function add($summand, $addend)
  {
    $sum = $summand ^ $addend;
    // 判断进位
    $carry = $summand & $addend;
    while ($carry <<= 1) {
      $summand = $sum;
      $addend = $carry;
      $sum = $summand ^ $addend;
      $carry = $summand & $addend;
    }
    return $sum;
  }

⒉ 减法

减法可以看作是减数为负数的加法,例如 2 - 1 可以看作是 2 + (-1)。

<?php
  require 'addition.php';

  function subtract($minuend, $subtrahend)
  {
    // 先求得减数的补码,然后求和
    $subtrahend = add(~$subtrahend, 1);

    return add($minuend, $subtrahend);
  }

⒊ 乘法

乘法也可以看作是加法的变种,例如 m * n 可以看作是 n 个 m 相加的结果。但乘法使用位运算还有更快捷的实现方式。例如 3 * 10:3 的二进制表示为 0011,10 的二进制表示为 1010

0 0 1 1

×      1 0 1 0

————————————

0 0 0 0

0 0 1 1 0

0 0 0 0 0 0

0 0 1 1 0 0 0

————————————

0 0 1 1 1 1 0

由上图可以看出,乘法计算的结果为:当乘数的位的值为 1 时,将被乘数按位左移相应的位数,最后将这些按位左移后得到的结果相加及时最后的结果。

<?php  require 'addition.php';
  function multiply($multiplicand, $multiplicator)
  {
    // 判断符号位
    $flag = ($multiplicand ^ $multiplicator) < 0 ? false : true;
    // 被乘数和乘数取绝对值
    $multiplicand = $multiplicand < 0 ? add(~$multiplicand, 1) : $multiplicand;
    $multiplicator = $multiplicator < 0 ? add(~$multiplicator, 1) : $multiplicator;
    $product = 0;
    $multiplicator = decbin($multiplicator);
    $length = strlen($multiplicator);
    for ($i = 0; $i < $length; $i ++) {
      if ($multiplicator[$i]) {
        $product += $multiplicand << $length - $i - 1;
      }
    }
    if (! $flag) {
      $product = add(~$product, 1);
    }
    return $product;
  }

⒋ 除法

同乘法类似,除法可以看作是被除数可以减去多少个除数。

<?php
  require 'addition.php';

  function divide($dividend, $divisor)
  {
    // 判断符号位
    $flag = ($dividend ^ $divisor) < 0 ? false : true;
    // 取得被除数符号位
    $dividend_flag = $dividend < 0 ? false : true;
    // 取绝对值
    $dividend = $dividend < 0 ? add(~$dividend, 1) : $dividend;
    $divisor = $divisor < 0 ? add(~$divisor, 1) : $divisor;

    $quotient = 0;
    $remainder = 0;

    if ($dividend < $divisor) {
      // 被除数小于除数的情况
      $remainder = $dividend;
      return 'quotient = ' . $quotient . ' remainder = ' . $remainder;
    }

    while ($dividend >= $divisor) {
      $i = 0;
      $mul_divisor = $divisor;

      while ($dividend >= ($mul_divisor << 1)) {
        $i ++;
        $mul_divisor <<= 1;
      }

      $dividend -= $mul_divisor;
      $quotient += 1 << $i;
    }

   $remainder = $dividend;
   if (! $flag) {
     $quotient = add(~ $quotient, 1);
   }
   if (! $dividend_flag) {
     $remainder = add(~$remainder, 1);
   }

   return 'quotient = ' . $quotient . ' remainder = ' . $remainder;
  }

以上。

需要指出的是,上面的代码在实现过成功并没有考虑数据的溢出。 两个很大的数相加可能会溢出;正数减负数也可能溢出;两个大数相乘也会溢出;任何数除以 0 都会溢出。

总结

以上所述是小编给大家介绍的PHP 使用位运算实现四则运算的代码,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

(0)

相关推荐

  • 用PHP实现的四则运算表达式计算实现代码

    PHP实现: 复制代码 代码如下: <?php /** * 计算四则运算表达式 */ error_reporting(E_ALL); $exp = '(1+2*(3+5)/4)*(3+(5-4)*2)'; $arr_exp = array(); for($i=0;$i<strlen($exp);$i++){ $arr_exp[] = $exp[$i]; } $result = calcexp( array_reverse($arr_exp) ); echo $exp . '=' . $resu

  • PHP巧妙利用位运算实现网站权限管理的方法

    首先我们先定义4个常量来设定四种权限: ===================================== define(ADD,1);//增加数据库记录的权限 define(UPD,2);//修改数据库记录的权限 define(SEL,4);//查找数据库记录的权限 define(DEL,8);//删除数据库记录的权限 ===================================== 接下来假设有3个用户: A用户拥有ADD-UPD-SEL-DEL四个权限,用位或运算计算A的

  • PHP实现的简单四则运算计算器功能示例

    本文实例讲述了PHP实现的简单四则运算计算器功能.分享给大家供大家参考,具体如下: php实现一个简单的四则运算计算器(还不支持括号的优先级).利用栈这种数据结构来计算表达式很赞. 这里可以使用栈的结构,由于php的数组"天然"就有栈的特性,这里直接就利用了数组.当然可以使用栈结构写,道理一样的. 前辈(波兰一位科学家)在计算带有括号的四则表达式,利用逆波兰算法(后缀表达法).简直神了!!其实代码code并不难,难的是算法的指导,要先理解算法,才能编码. <?php $num_a

  • 老生常谈PHP位运算的用途

    在实际应用中可以做用户权限的应用 我这里说到的权限管理办法是一个普遍采用的方法,主要是使用到"位运行符"操作,& 位与运算符.| 位或运行符.参与运算的如果是10进制数,则会被转换至2进制数参与运算,然后计算结果会再转换为10进制数输出. 它的权限值是这样的 2^0=1,相应2进数为"0001″(在这里^我表示成"次方",即:2的0次方,下同) 2^1=2,相应2进数为"0010″ 2^2=4,相应2进数为"0100″ 2^3=

  • PHP 使用位运算实现四则运算的代码

    计算机最基本的操作单元是字节,一个字节由8个位组成,一个位只能存储一个0或1.所有数据在计算机中都是采用二进制,即 1 和 0 的编码存储和运算. 这次尝试在 PHP 中使用位运算实现四则运算,首先介绍一些基本概念: 原码:将最高位作为符号位(0表示正,1表示负),其它数字位代表数值本身的绝对值 反码:正数反码和原码一样:如果是负数,符号位不变,其余各位取反 补码:正数补码和原码一样:负数补码为反码加 1 计算机中的数使用 补码  的形式存储 ⒈ 加法 二进制中只有 0 和 1,0 + 0.0

  • 批处理位运算演示代码

    在论坛里看到netbenton的那个不用call调用函数的帖子(下面贴有链接)后,突然记起以前自己写的一个位运算演示的代码(用call来调用函数,现改用netbenton的方法另类的调用),现拿出来和大家分享一下,希望能给初学者一些小小的帮助 @echo off title 位运算示例 code by:cn-bathome-more echo. echo.位运算名词解释(个人理解): echo. echo.位运算: 按操作数在计算机内表示的二进制数逐位进行逻辑运算或移位运算. echo.与: 全

  • bat批处理位运算实例代码

    发现很多新手对于批处理中set/a的位运算的概念有点模糊,我也是,什么"异.或.与.逻辑移位",看的云里雾里,头脑发胀,于是就有了下面的代码. @echo off if "%~1" equ "" exit/b :begin setlocal enabledelayedexpansion set "Var=0123456789ABCDEF" set/p number=Input: if /i "%number%&quo

  • C语言 位运算详解及示例代码

    所谓位运算,就是对一个比特(Bit)位进行操作.在<二进制思想以及数据的存储>一节中讲到,比特(Bit)是一个电子元器件,8个比特构成一个字节(Byte),它已经是粒度最小的可操作单元了. C语言提供了六种位运算符: 运算符 & | ^ ~ << >> 说明 按位与 按位或 按位异或 取反 左移 右移 按位与运算(&) 一个比特(Bit)位只有 0 和 1 两个取值,只有参与&运算的两个位都为 1 时,结果才为 1,否则为 0.例如1&1

  • java位运算加密示例

    创建一个类,通过位运算中的"^"异或运算符把字符串与一个指定的值进行异或运算,从而改变字符串每个字符的值,这样就可以得到一个加密后的字符串.当把加密后的字符串作为程序输入内容,再与那个指定的值进行异或运算,实现把加密后的字符串还原为原有字符串的值. 复制代码 代码如下: import java.util.Scanner;public class Example {    public static void main(String[] args) {        Scanner sc

  • golang简单位运算示例

    本文实例讲述了golang简单位运算.分享给大家供大家参考,具体如下: 复制代码 代码如下: // http://play.golang.org/p/idG7Ri_krU package main import "fmt" func main() {     var n uint8 = 6     fmt.Printf("%s\n%08b\n%08b\n\n", "6<<1 左移1位", n, n<<1)     fmt.

  • 浅析关于PHP位运算的简单权限设计

    1.写在最前面最近想写一个简单的关于权限处理的东西,之前我也了解过用二进制数的位运算可以出色地完成这个任务.关于二进制数的位运算,常见的就是"或.与.非"这三种简单运算了,当然,我也查看了下PHP手册,还有"异或.左移.右移"这三个运算.记得上初中时数学老师就开始唠叨个不停了,在此我也不想对此运算再作额外的说明,直接进入正题. 2.如何定义权限将权限按照2的N次方来定义值,依次类推.为什么要这样子定义呐?这样子定义保证了每个权限值(二进制)中只有一个1,而它恰好对应

  • 位运算实现十进制转换为二进制

    代码如下: 复制代码 代码如下: #include <iostream>        //将十进制数转化为二进制数,位运算的取位操作  using namespace std;  int main()  {         unsigned short i;         cout << "请输入一个小于65536的正整数" << endl;         cin >> i;         for(int j=15; j >

  • c语言中用位运算实现加法技巧介绍

    用位运算实现加法也就是计算机用二进制进行运算,32位的CPU只能表示32位内的数,这里先用1位数的加法来进行,在不考虑进位的基础上,如下 复制代码 代码如下: 1 + 1 = 0 1 + 0 = 1 0 + 1 = 1 0 + 0 = 0 很明显这几个表达式可以用位运算的"^"来代替,如下 复制代码 代码如下: 1 ^ 1 = 0 1 ^ 0 = 1 0 ^ 1 = 1 0 ^ 0 = 0 这样我们就完成了简单的一位数加法,那么要进行二位的加法,这个方法可行不可行呢?肯定是不行的,矛盾

  • 通过SQL Server的位运算功能巧妙解决多选查询方法

    无论使用int还是varchar,对于Status的多选查询都是不易应对的.举例,常规思维下对CustomerStatus的Enum设置如下: 复制代码 代码如下: [Serializable] public enum CustomerStatus { New = 0, Active = 1, Overdue = 2, Suspended = 3, Closing = 4, Closed = 5 } 在数据库中以int形式存储了Status值. 如果我在页面中想一次搜索状态为Active,Ove

随机推荐