今天看到《编码:隐匿在计算机软硬件背后的语言》的第十二章:二进制加法器。讲述了全加器,半加器的原理以及如何实现加法。实现加法时所使用的全加器,半加器中包含的所有逻辑门在C语言中都有相应的运算符,就想着能不能利用C语言中的运算符实现不用加号的加法运算。

  首先,半加器的样子:               全加器的样子:

    

  二进制加法器的样子:

  

  以下为完全按照二进制加法器的计算流程写成的C语言代码

  1. #include"stdio.h"
  2. int add(int a,int b)
  3. {
  4. ,aa,bb,t=;
  5. unsigned i;//由于需要计算31位,但是int的第32位是符号位,故定义成无符号型
  6. ;i<=)
  7. {
  8. aa=i&a;//a的本位
  9. bb=i&b;//b的本位
  10. sum|=aa^bb^t;//aa 和 bb 和 前位的进位 求和
  11. t&=aa^bb;//aa 和 bb 的加和位 与 前位的进位 求进位位
  12. t|=aa&bb;//aa 和 bb 的进位位 与 上式的进位位 求或 (如果有进位,上下两个式子只有一个需要进位)
  13. t<<=;
  14. }
  15. return sum;
  16. }
  17. int main()
  18. {
  19. int a,b;
  20. while(~scanf("%d%d",&a,&b))
  21. printf("%d %d\n",add(a,b),a+b);
  22. ;
  23. }

  记得以前在网上见到过不使用加号实现加法的方法,于是又从网上找了找。一共找到了三个方法,其中第一种思想与二进制加法器的思想基本相同,但因为不是一位一位运算的,所以有一个地方略有不同,以下为代码

  1. #include"stdio.h"
  2. int add(int a,int b)
  3. {
  4. )
  5. return a;
  6. int sum=a^b;//sum和a存储的是加和位
  7. ;//carry和b存储的是进位位
  8. //这里比最开始的代码少了一个求或的运算
  9. //因为这个代码是所有位一起运算的,所以当某一位运算有进位到下一位时
  10. //下一位的两个操作数不会存在都是1的情况
  11. //因为一开始都是1的话,在本次计算之前就已经进位到下一位了
  12. //而最开始的一位一位的计算方法,存在这种情况,所以需要单独处理
  13. return add(sum,carry);
  14. }
  15. int main()
  16. {
  17. int a,b;
  18. while(~scanf("%d%d",&a,&b))
  19. printf("%d %d\n",add(a,b),a+b);
  20. ;
  21. }

  第二种第三种方法属于利用计算机内存及函数的运算机制来计算的方法,以下为第二种方法代码

  1. #include"stdio.h"
  2. int main()
  3. {
  4. int a,b;
  5. while(~scanf("%d%d",&a,&b))
  6. printf("%d\n",printf("%*s%*s",a,"",b,""));
  7. ;
  8. //这种方法利用的是printf函数的返回值及*操作符的原理来计算两个数相加的
  9. //1.因为printf函数是字符流的格式化输出函数
  10. // 所以printf函数的返回值是:输出字符串中所含字符个数(int型)
  11. //2.printf函数中的*操作符用来指定输出字符串的宽度
  12. // 这个值由后面对应字符串参数前的一个整数参数指定
  13. //这样在上例中printf输出的字符串是最大宽度为a+b的两个空字符,不足的地方用空格补全
  14. //最终函数的返回值是a+b
  15. //但是这个方法有一个问题:printf函数中的printf函数输出的空格会输出在加和结果之前
  16. //因此这个方法并不能按照正常格式输出a+b
  17. }

  以下为第三种方法的代码

  1. #include"stdio.h"
  2. int add(int a,int b)
  3. {
  4. return (int)(&((char*)a)[b]);
  5. //这个求加和的思路是利用数组在内存中存储的连续性
  6. //a[b]与*(a+b)是等价的
  7. //所以要求a+b的值只需求出a[0]到a[b]占内存的宽度除去单个数据所占宽度即可
  8. //具体计算公式:a+b=(int)(&a[b]-&a[0])/sizeof(a[0])
  9. }
  10. int main()
  11. {
  12. int a,b;
  13. while(~scanf("%d%d",&a,&b))
  14. printf("%d %d\n",add(a,b),a+b);
  15. ;
  16. }

  a+b=a-(-b)这种抖机灵的方法就不提了...

  以下为参考

  第一种方法:求两个数的和(不用+-*/)

  第二种方法:C语言中不使用操作符实现两个数相加

  第三种方法:C语言中如何不使用加号,完成两个数字相加

C语言不使用加号实现加法运算的几种方法的更多相关文章

  1. Java实现大数加法运算的几种方法

    大数加法 思路一:定义String变量str1和str2分别存储输入的两个大数,定义num1[]和num2[]两个int型数组,将两个字符串分别逐个字符逆序存入数组,定义sum[]数组存放求和结果,使 ...

  2. 在shell script中进行数值运算的两种方法

    方法1:使用"$((计算式))"的方式进行数值运算,不需要使用declare命令显示声明数值型变量来存储计算结果: 方法2:使用declare命令配合"-i"选 ...

  3. 华为OJ机试题目:两个大整数相乘(纯C语言实现两个大整数相乘,两种方法实现大数相乘)

    题目描述: 输出两个不超过100位的大整数的乘积. 输入: 输入两个大整数,如1234567 123 输出: 输出乘积,如:151851741 样例输入: 1234567 123 样例输出: 1518 ...

  4. c语言分析函数调用关系图(call graph)的几种方法

    一.基于 Doxygen或 lxr 的API形式的文档系统. 二.基于CodeViz, CodeViz是<Understanding The Linux Virtual Memory Manag ...

  5. C#语言————拼接、插入、替换、删除四种方法

    StringBuilder sb = new StringBuilder("hello"); sb.Append("world");//拼接 sb.Insert ...

  6. shell 中变获取值及运算的几种方法

    num=$(tail ./image/1.txt -n 1) num=$(($num+1))

  7. linux下运算的几种方法

    1.expr 1.1 最简单的用法 yan@yan:~$ \* yan@yan:~$ 1.2 bash脚本对于expr yan@yan:~$ cat expr1.sh #!/bin/bash PATH ...

  8. C++大小写转换和性能(C语言,C++,API,STL一共4种方法)

    大小写转换和性能 前言 本文主要讨论最基本的一些大小写转换函数和API,不讨论一些常见的字符串程序库里面的大小写转换接口,另外本文的落脚点是这些转换函数的性能和日常开发中遇到的一些问题. 不考虑范围 ...

  9. c语言提取浮点型数据的整数部分与小数部分几种方法

    一 前记 最近涉及到把各种传感器的数据通过wifi和bt传输出去,这就涉及到了浮点传输的问题,为了方便传输,笔者的做法一般是把小数和整数部分分开,分别传输,这就比较简单明晰了. 二 方法论 其实,把浮 ...

随机推荐

  1. 悟空模式-java-单例模式

    [那座山,正当顶上,有一块仙石.其石有三丈六尺五寸高,有二丈四尺围圆.三丈六尺五寸高,按周天三百六十五度:二丈四尺围圆,按政历二十四气.上有九窍八孔,按九宫八卦.四面更无树木遮阴,左右倒有芝兰相衬.盖 ...

  2. 解决:jsp 页面不全,response 内容不完整

    前言:今天 jsp 页面输出不完整这个问题困扰了我几个小时,终于发现问题并解决了. 环境: tomcat 8.0.17 x64 jsp springmvc vue 问题: 本来页面正常,但加了几行代码 ...

  3. JAVA中的泛型(Generic)

    Java泛型(Generic)简介 泛型是jdk1.5版本以后推出来的,表示类型参数化,让java能更具有动态性一些,让类型能变成参数传递. 要我自己感觉的话,泛型本身没啥用,跟反射在一起用,就体现出 ...

  4. [移动端WEB] 移动端input标签按钮为什么在苹果手机上还有一层白色?

    移动端input标签按钮为什么在苹果手机上还有一层白色? 解决办法:其实蛮简单的,就加一个属性就好了 input { outline:0px ; -webkit-appearance: none; } ...

  5. js返回一组日期中最近连续的天数

    用js获取一组日期(并把当天算入)中连续的天数 刚开始可能想到单纯的比较日期大小判断连续, 而又有大小月,平闰年这些因素,还是时间戳来的安全; 首先得有一组日期,比如: var arr = [ '20 ...

  6. Laravel 支付宝支付异步通知

    支付宝支付通知有前端通知(GET)和服务器异步通知(POST) 在配置支付宝支付时,需要注意的问题就是支付宝的回调操作: 1.在laravel中应该将支付宝通知路径组织csrf验证,否则会导致419错 ...

  7. elixir mac环境

    1.升级brew brew update 2.安装 erlang brew install erlang 3.安装Elixir: brew install elixir 终端 iex iex> ...

  8. 使用Callable和Future接口创建线程

    具体是创建Callable接口的实现类,并实现clall()方法.并使用FutureTask类来包装Callable实现类的对象,且以此FutureTask对象作为Thread对象的target来创建 ...

  9. JS DOM节点增删改查 属性设置

    一.节点操作 增 createElement(name)创建元素 appendChild();将元素添加   删 获得要删除的元素 获得它的父元素 使用removeChild()方法删除 改 第一种方 ...

  10. ES6-let & const

    let和const命令 let 它的用法类似于var,但是所声明的变量,只在let命令所在的代码块内有效. for(let i = 0; i < arr.length; i++){} 用let命 ...