Java不用算数运算符来实现求和方法

今天遇到了这样一个题

题目说了不能用算数运算符,那么我们就只能从 逻辑运算符 和 移位运算符 入手了。

我们知道 ^ (异或)操作是对两个数进行无进位求和,如果两个数相加本来就不产生进位,那么该和就是两数之和。 这就是解题的关键所在。一般来说,两数相加是会产生进位的,而要得到正确的和,应该是在 “无进位之和” 的基础上加上进位,那我们首先应该得到进位。我们知道,当两个数对应位置都为1的情况下,才会有进位的产生,即对应位置 A&B==1的条件下,就可以得到每一位的进位,但是进位是将这个1加到对应的更高一位,所以我们将得到的进位整体进行左移一位,再和之前得到的 “无进位之和” 相加,就可以得到两数之和。

我们发现这里就可以无限套娃了,要得到 “无进位之和” 和 “产生的进位” 之和,那么将这两个数再分别看做新的两个数,对其求和。也是重复之前的操作,直到两数不能产生进位,就可以直接通过 ^ 运算得到结果。

假设我们求 23 + 16 的值

根据上述思路,我们很容易就可以写出代码

public static int addAB(int A, int B) {
		// 当两数的产生的进位为 0,就退出循环,返回其无进位和,就是结果
        while ((A & B) != 0) {
            int A_B = A ^ B;// 无进位求和
            int AB = (A & B) << 1;// 得到进位
            // 接下来就是求 得到的进位 + 无进位之和,重复前面的操作,直到不产生进位
            A = A_B;
            B = AB;
        }
        // 最后返回新的无进位之和
        return (A ^ B);
    }

那么为了验证它的正确性,我们这里使用对数器,将该函数与 ’ + ’ 运算符比较。

public static void main(String[] args) {
    int count = 1_0000_0000;// 比较次数 100000000次
    Random random = new Random();// 生成随机数字
    boolean flag = true;// 相等则为 true

    for (int i = 0; i < count; i++) {
        int num1 = random.nextInt(Integer.MAX_VALUE/2);// 随机正数1
        int num1_2 = random.nextInt(Integer.MAX_VALUE/2);// 随机正数2
        // 随机正数1 + 随机正数2
        if ((num1+num1_2) != addAB(num1,num1_2)){
            // 有一次不相等的,则退出循环
            flag = false;
            break;
        }

        int num2 = -random.nextInt(Integer.MAX_VALUE/2);// 随机负数1
        int num2_2 = -random.nextInt(Integer.MAX_VALUE/2);// 随机负数2
        // 随机负数1  + 随机负数2
        if ((num2+num2_2) != addAB(num2,num2_2)){
            // 有一次不相等的,则退出循环
            flag = false;
            break;
        }

        int num3 = random.nextInt(Integer.MAX_VALUE);// 随机正数
        int num4 = -random.nextInt(Integer.MAX_VALUE);// 随机负数
        // 随机正数  + 随机负数
        if ((num3+num4) != addAB(num3,num4)){
            // 有一次不相等的,则退出循环
            flag = false;
            break;
        }
    }
    System.out.println(flag);
}

运行结果:

最后输出结果为 true ,说明我们计算随机产生的 正数+正数、负数+负数、正数+负数 分别100000000次,没有一次出错,说明该函数可靠。

到此这篇关于Java不用算数运算符来实现求和方法的文章就介绍到这了,更多相关Java 求和 内容请搜索我们以前的文章或继续浏览下面的相关文章希望大家以后多多支持我们!

(0)

相关推荐

  • Java生成10个1000以内的随机数并用消息框显示数组内容然后求和输出

    本文最终结果大概是这样的,使用java技术随机生成10个数,然后填充一个数组并在消息框中显示数组内容,接着对数组求和输出,将结果显示在消息框中. 设计思路:可以先用Math.Random()*1000生成1000以内随机数,然后依次存入数组中,然后读取数组,输出随机数,同时进行加法计算,最后将所有结果以消息框形式输出. 程序流程图: 源代码: package 随机数求和; import javax.swing.*; public class Sum { public static void ma

  • Java递归求和1+2+3+...+n实例详解

    Java递归求和1+2+3+...+n public class Sum { public static int count(int n) { if (n > 1) { return count(n - 1) + n; } else { return n; } } public static void main(String[] args) { System.out.println(Sum.count(100)); } } 扩展学习 输入一个数: 4 10 代码: public class De

  • Java数组的遍历与求和知识点

    一维数组遍历与求和: public class OneArry{ public static void main(String[] args) { double[] num = {1.9, 2.9, 3.4, 3.5,10,-1}; num[0]=new Double(2); //通过下标把1.9变为2.0 double sum = 0; for (int i = 0; i < num.length; i++) { //遍历 System.out.println(num[i]); sum+=nu

  • Java三种循环求和方法

    注意:100之和为5050 普通for循环: public class HundredSum { public static void main(String[] args){ int x=0; for(int i=1;i<=100;i++){ x=x+i;//x+=i; } System.out.print(x); } } while循环: public class HundredSum { public static void main(String[] args){ int x=0; in

  • java集合求和最大值最小值示例分享

    复制代码 代码如下: package com.happyelements.athene.game.util; import static com.google.common.base.Preconditions.checkNotNull; import java.util.Collection; import com.google.common.collect.Lists; /** * Math工具类 *  * @version 1.0 * @since 1.0 */public class M

  • Java不用算数运算符来实现求和方法

    今天遇到了这样一个题 题目说了不能用算数运算符,那么我们就只能从 逻辑运算符 和 移位运算符 入手了. 我们知道 ^ (异或)操作是对两个数进行无进位求和,如果两个数相加本来就不产生进位,那么该和就是两数之和. 这就是解题的关键所在.一般来说,两数相加是会产生进位的,而要得到正确的和,应该是在 “无进位之和” 的基础上加上进位,那我们首先应该得到进位.我们知道,当两个数对应位置都为1的情况下,才会有进位的产生,即对应位置 A&B==1的条件下,就可以得到每一位的进位,但是进位是将这个1加到对应的

  • Java 使用 HttpClient 发送 GET请求和 POST请求

    目录 概述 认证方式 基础认证Auth 用户名密码认证 Bearer Token 认证 配置超时 生成 RequestConfig 设置超时时间 概述 日常工作中,我们经常会有发送 HTTP 网络请求的需求,概括下我们常见的发送 HTTP 请求的需求内容: 可以发送基本的 GET/POST/PUT/DELETE 等请求: HTTP请求,可以附带认证,包括基本的 用户名/密码 认证,以及 Bearer Token 认证: 请求可以自定义 超时时间: HTTP请求可以带参数,也可以不带参数: HTT

  • java 获取用户的MAC地址多种方法实例详解

    java实现获取用户的MAC地址方法: 方法一:将本机地址与局域网内其他机器区分开来 /** * 根据IP地址获取mac地址 * @param ipAddress 127.0.0.1 * @return * @throws SocketException * @throws UnknownHostException */ public static String getLocalMac(String ipAddress) throws SocketException, UnknownHostEx

  • Java线程池的几种实现方法及常见问题解答

    工作中,经常会涉及到线程.比如有些任务,经常会交与线程去异步执行.抑或服务端程序为每个请求单独建立一个线程处理任务.线程之外的,比如我们用的数据库连接.这些创建销毁或者打开关闭的操作,非常影响系统性能.所以,"池"的用处就凸显出来了. 1. 为什么要使用线程池 在3.6.1节介绍的实现方式中,对每个客户都分配一个新的工作线程.当工作线程与客户通信结束,这个线程就被销毁.这种实现方式有以下不足之处: •服务器创建和销毁工作的开销( 包括所花费的时间和系统资源 )很大.这一项不用解释,可以

  • java 避免出现NullPointerException(空指针)的方法总结

    java 避免出现NullPointerException(空指针)的方法总结 Java应用中抛出的空指针异常是解决空指针的最好方式,也是写出能顺利工作的健壮程序的关键.俗话说"预防胜于治疗",对于这么令人讨厌的空指针异常,这句话也是成立的.值得庆幸的是运用一些防御性的编码技巧,跟踪应用中多个部分之间的联系,你可以将Java中的空指针异常控制在一个很好的水平上.顺便说一句,这是Javarevisited上的第二个空指针异常的帖子.在上个帖子中我们讨论了Java中导致空指针异常的常见原因

  • Java从控制台读入数据的几种方法总结

    这里记录Java中从控制台读入信息的几种方式,已备后查! (1)JDK 1.4(JDK 1.5和JDK 1.6也都兼容这种方法) public class TestConsole1 { public static void main(String[] args) { String str = readDataFromConsole("Please input string:); System.out.println("The information from console: + st

  • 简单理解Java的垃圾回收机制与finalize方法的作用

    垃圾回收器要回收对象的时候,首先要调用这个类的finalize方法(你可以 写程序验证这个结论),一般的纯Java编写的Class不需要重新覆盖这个方法,因为Object已经实现了一个默认的,除非我们要实现特殊的功能(这 里面涉及到很多东西,比如对象空间树等内容). 不过用Java以外的代码编写的Class(比如JNI,C++的new方法分配的内存),垃圾回收器并不能对这些部分进行正确的回收,这时就需要我们覆盖默认的方法来实现对这部分内存的正确释放和回收(比如C++需要delete). 总之,f

  • Java编程调用微信支付功能的方法详解

    本文实例讲述了Java编程调用微信支付功能的方法.分享给大家供大家参考,具体如下: 微信开发文档地址:https://mp.weixin.qq.com/wiki/home/ 从调用处开始 我的流程: 1.点击"支付"按钮,去后台 --> 2.后台生成支付所需数据返回页面 --> 3.页面点击"确认支付"调用微信支付js.完成支付功能. 支付按钮 <div class="button" id="pay" onc

  • java读取XML文件的四种方法总结(必看篇)

    JAVA操作XML文档主要有四种方式,分别是DOM.SAX.JDOM和DOM4J,DOM和SAX是官方提供的,而JDOM和DOM4J则是引用第三方库的,其中用的最多的是DOM4J方式.运行效率和内存使用方面最优的是SAX,但是由于SAX是基于事件的方式,所以SAX无法在编写XML的过程中对已编写内容进行修改,但对于不用进行频繁修改的需求,还是应该选择使用SAX. 下面基于这四种方式来读取XML文件. 第一,以DOM的方式实现. package xmls; import org.w3c.dom.D

随机推荐