最近在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. mycat 离散分片 -&gt; 程序指定分区的分片

    1.程序指定分区的分片 此规则是在运行阶段有应用自主决定路由到那个分片. 此方法为直接依据字符子串(必须是数字)计算分区号(由应用传递參数.显式指定分区号). 2,加入配置文件 在function.x ...

  2. C++实践參考——二进制文件浏览器

    [项目-二进制文件浏览器] (1)做一个相似BinaryViewer的查看二进制文件的程序.输入文件名称后,能够以16进制和ASCII对比的方式列出该文件的内容.能够參考下图: 提示:循环中,一次读入 ...

  3. ArcGIS Engine 编辑- IWorkspaceEdit

    转自原文 ArcGIS Engine 编辑- IWorkspaceEdit 这个例子中,我创建了1000条要素,并结合缓冲将数据写到文件中,并且添加了时间统计,当然数据是我捏造的,还请原谅,这个花费的 ...

  4. 【Bash百宝箱】Linux shell学习

    shell特点-- Linux有多种shell能够使用,默认的为bash,bash有以下几个主要特点. 1.命令记忆能力 在命令行中按上下键能够找到一个前/后输入的命令.这些命令记录在-/.bash_ ...

  5. 从头认识Spring-2.3 注解装配-@autowired(5)-限定器@Qualifier(1)

    这一章节我们来具体讨论一下配合@autowired一起使用的限定器@Qualifier. 1.domain(重点) 蛋糕类: package com.raylee.my_new_spring.my_n ...

  6. [Angular] Subscribing to the valueChanges Observable

    For example we have built a form: form = this.fb.group({ store: this.fb.group({ branch: '', code: '' ...

  7. POJ 3252 Round Numbers(数位dp&amp;记忆化搜索)

    题目链接:[kuangbin带你飞]专题十五 数位DP E - Round Numbers 题意 给定区间.求转化为二进制后当中0比1多或相等的数字的个数. 思路 将数字转化为二进制进行数位dp,由于 ...

  8. Android JNI -基础篇

    JNI(Java Native Interface,JAVA本地接口) 可以使Java代码和其他语言写的代码(如C/C++代码)进行交互.为什么要进行交互? 首先,Java语言提供的类库无法满足要求, ...

  9. 【42%】【hdu1166】排兵布阵(树状数组解法&&线段树解法)

    Problem Description C国的死对头A国这段时间正在进行军事演习,所以C国间谍头子Derek和他手下Tidy又开始忙乎了.A国在海岸线沿直线布置了N个工兵营地,Derek和Tidy的任 ...

  10. 【codeforces 760A】Petr and a calendar

    time limit per test2 seconds memory limit per test256 megabytes inputstandard input outputstandard o ...