最近在LeetCode 上刷题,遇到一个非常有趣的题目,题目的大概意思就是在不使用运算符的情况下实现两个数的加法。。。原题点这里》》》

说实话,刚看到这题目,我是一脸懵逼的。

后来仔细想想,如果不能用运算符,那肯定是用原始方法了(位运算)。

后来,的确也证明我的想法是正确的。不过还是有种思路没想到,是参考了网上的。

在这里,我就来说说我所知道的两个方案。方法low,大牛可以点击右上角的×了。。。

注:以下讨论均基于整数之间的四则运算!部分来自网络~

【加法】

方案一(推荐):

此方法参照计算机的二进制计算

分两步:

  一:先进行没有进位的加法运算。可用 a^b;

  二:处理进位信息。a&b 可得到进位的位置信息,然后左移一位,就是两数相加后的进位信息了。所以可以用 (a & b) << 1;

    然后就是把前面得到的没有进位的和加上进位信息了,直到进位为0为止。因此代码可以这么写:

public static int GetSum(int a, int b)
{
if (b == )
{
return a;
} int sum = a ^ b;
int carry = (a & b) << ; int result = GetSum(sum, carry); return result;
}

方案二:

此方案在C#中不常使用。将利用指针的偏移来进行加法运算。

先上代码:

unsafe public static int GetSum_Point(int a, int b)
{
unsafe
{
byte* c = (byte*)a;
int d = (int)&c[b];
return d;
}
}

此处附上C#在VS2015中使用指针的方法(传送门

例如a=5,b=10

c=(byte*) a,此时c的地址为0x00000005

c[b] 就是c的地址偏移sizeof(byte)*b

最终得到了c[b]的地址就是0x0000000f,即通过int强制转换得到15 。

【减法】

按理来说,只要加法解决了,后面的运算都是小菜一碟了。本着思考的态度,我们还是要想想怎么用位运算来实现减法。

总的来说还是有两个方案实现的,以下依次来说说。

方案一:

原理其实也是参考计算机计算减法的操作。

这里需要用到一个叫“补码”的东西,不懂的同学点这里》》》

我们都知道两个数的减法可以当作一个正数和一个负数的加法。照这个思路,我们可以这么写:

public static int GetMargin(int a, int b)
{
return GetSum(a, GetSum(~b, 1));
}

方案二:

此方案和【加法】中的方案一类似。都是二进制的计算

我们分以下几步来看:(以a - b为例)

  1.如果b 的值为0,那么结果显而易见就是a 了。

  2.b 不为0 的情况下,我们仍然先不考虑借位,先将被减数和减数同为1 的位置去掉。

    第一步,找出减数和被减数同为1 的位置。可使用 sameNum = a&b; 来实现;

    第二步,分别将被减数和减数同为1 的位置去掉1 ,这里可以用 a ^= sameNum; b ^= sameNum;

  3.此时,减数和被减数相同位只存在以下三种情况:

    1. 被减数:0 ;减数: 0;差:0;
    2. 被减数:0 ;减数: 1;差:1;
    3. 被减数:1 ;减数: 0;差:1;

  4.通过对被减数、减数和差的分析,很容易就能知道差值应该是被减数和减数的按位或的结果。于是我们便有:a | b 得到临时的结果;

  5.此时再考虑借位问题。很明显只有在减数为1的情况下,被减数与之对应的左一位才会出现借位,于是借位便可以用 b << 1 ; 来表示。

  6.再把临时结果减去借位,直到借位为0 ,得到的结果便是最终的结果了。综上,代码如下:

public static int GetMargin(int a, int b)
{
while (b != )
{
// 去掉被减数和减数中同为1的位
int sameNum = a & b;
a ^= sameNum;
b ^= sameNum; // 此时,a 和 b 不存在同时为1 的位
// 0 - 1 和 1 - 0 都为1
a |= b; // 得到相减的临时结果(不考虑借位)
b = b << ; // 减数为1 时,必有借位
}
return a;
}

【乘法】

1.先考虑正整数之间的乘法运算。

  在二进制中,每向左移动一次,都相当于原始数乘以2。而每个数据都可以写成k0×20+k1×21+...+km×2m的形式。因此我们可以得到以下式子:

  a x b = ax20xk0 +  ax21xk1 + .... + ax2mxk其中ki = {0, 1};

  因此我们可以很容易写出以下代码:

public static int GetProduct(int a, int b)
{
// 1.先只考虑正整数的相乘 int result = ;
for (int bits = ; bits != ; bits <<= )
{
if ((bits & b) != )
{
result = GetSum(result, a);
}
a <<= ;
} return result;
}

2.接下来,开始考虑正负号的情况(考虑溢出的情况)。

  这里有个简单的办法,直接判断a、b和0 的关系来判断正负。本着学习的态度(耳熟

不使用运算符(+、-、*、/) 来进行四则运算(C#)的更多相关文章

  1. Java开发笔记(八)五种算术运算符

    计算机科学起源于数学,早期的计算机也确实多用于数学运算,以至于后来的各路编程语言,仍然保留着古老的加减乘除四则运算.这四则运算在Java语言中有专门的运算符加以表示,像加法符号“+”对应Java的“+ ...

  2. 第三周结对项目--小学生四则运算CAI软件汇报及总结(UI/web)

    前言: 这周是和我队友苏卫喜一起结对开发,我主要是写项目文档需求分析,她是通过我的需求文档来进行做思维导图,之后我们通过思维导图一起讨论用户界面设计. 以下就是我的需求分析1.0版本 1.   软件名 ...

  3. C语言基础知识-运算符与表达式

    C语言基础知识-运算符与表达式 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 一.常用运算符分类 1>.算术运算符 用于处理四则运算. 2>.赋值运算符 用于将表达式的 ...

  4. 21.Python算术运算符及用法详解

    算术运算符是处理四则运算的符号,在数字的处理中应用得最多.Python 支持所有的基本算术运算符,如表 1 所示. 表 1 Python常用算术运算符 运算符 说明 实例 结果 + 加 12.45 + ...

  5. C++之运算符_算数运算符

    运算符 **作用:**用于执行代码的运算 | **运算符类型** | **作用** || -------------- | -------------------------------------- ...

  6. Python基础知识之3——运算符与表达式

    一.概念: 运算符:运算符用于执行程序代码运算,会针对一个以上操作数项目来进行运算.比如10+4=14,其中操作数是 10 和 4,运算符是“+” . Python 语言主要支持运算符类型有:算术运算 ...

  7. C语言 运算符

    C语言 运算符 运算符优先级别 优先级 运算符 名称或含义 使用形式 结合方向 说明 1 [] 数组下标 数组名[常量表达式] 左到右 -- () 圆括号 (表达式)/函数名(形参表) -- . 成员 ...

  8. Python语言基础-语法特点、保留字与标识符、变量、基本数据类型、运算符、基本输入输出、Python2.X与Python3.X区别

    Python语言基础 1.Python语法特点 注释: 单行注释:# #注释单行注释分为两种情况,例:第一种#用于计算bim数值bim=weight/(height*height)第二种:bim=we ...

  9. 零基础学Python--------第2章 Python语言基础

    第2章  Python语言基础 2.1 Python语法特点 2.11注释 在Python中,通常包括3种类型的注释,分别是单行注释.多行注释和中文编码声明注释. 1.单行注释 在Python中,使用 ...

  10. STL心得

    熟悉c++版算法竞赛程序框架 理解变量引用的原理 熟练掌握string和stringstream 熟练掌握c++结构体的定义和使用,包括构造函数和静态成员变量 了解常见的可重载运算符,包括四则运算,赋 ...

随机推荐

  1. ATL入门

    服务端代码----------------------------------------------------------------------------------------------- ...

  2. Batch Normalization 反向传播(backpropagation )公式的推导

    What does the gradient flowing through batch normalization looks like ? 反向传播梯度下降权值参数更新公式的推导全依赖于复合函数求 ...

  3. thinkphp3.2使用join联合查询

    $members=$model->table('zhope_card A') ->join('zhope_user U ON A.adduser=U.id',"LEFT" ...

  4. Matlab-------regexp正则表达式

    转自原文 Matlab-------regexp正则表达式 句点符号 '.' ——匹配任意一个(只有一个)字符(包括空格). 例如:t.n,它匹配tan. ten.tin和ton,还匹配t#n.tpn ...

  5. [Elm] Functions in Elm

    Functions are an important building block in Elm. In this lesson we will review stateless functions, ...

  6. ios开发网络学习AFN三:AFN的序列化

    #import "ViewController.h" #import "AFNetworking.h" @interface ViewController () ...

  7. Windows Phone 8.1 控件

    如果你已经开始了 Windows Phone 8.1 的学习,就会发现许多在 8.0 下的控件在 8.1 中都发生了变化,以下就谈谈几个 8.1 下的新控件以及与 8.0 控件的改变. 1. Text ...

  8. SPOJ4491. Primes in GCD Table(gcd(a,b)=d素数,(1&lt;=a&lt;=n,1&lt;=b&lt;=m))加强版

    SPOJ4491. Primes in GCD Table Problem code: PGCD Johnny has created a table which encodes the result ...

  9. window对象属性alert、confirm、prompt怎么使用?

    window对象属性alert.confirm.prompt怎么使用? 一.总结 1.参数依次复杂,返回值依次复杂,但是感觉都是一一继承的,所以很好想也很好写. 二.window对象alert.con ...

  10. Mysql用户本机登陆不成功的解决

    mysql新建一个用户,本机不能登陆,但是远程能够登陆,不知什么原因,最后查阅 http://blog.itpub.net/12679300/viewspace-1453490/ 这篇文章得以解决,进 ...