Java为什么使用补码进行计算的原因分析

我们主要要解决的问题就是负数的表示,而众所周知,绝对值相等的两个正负数之和为0。

假设我们有正数 0000 0000 0000 1111,我们如何表示其相反数呢?一般我们的思路是,找一个数,跟它相加的结果等于0,但是我们发现,要找出一个与它相加后结果等于0的数还是要略加思考一下的(因为要计算进位),所以,为何不找出一个与它相加后结果是1111 1111 1111 1111的数,然后该数+1即是我们所要的答案啦。

于是,很容易的, 0000 0000 0000 1111 + 1111 1111 1111 0000 + 1 = 1111 1111 1111 1111 + 1 = (1)0000 0000 0000 0000

一目了然,1111 1111 1111 0001 就是我们想要的答案了,那么我们是怎么得到这个相反数的呢?

首先,找出一个数与它加起来结果是全1的,这个数便是它的反码,然后这个数再加1,这便是它的相反数了,也是我们说的补码。

我们检验一下0的情况,0000 + 1111 + 1 =(1)0000,其中1111 + 1 = (1)0000 = 0000,即+0和-0的二进制表示均为0000。

一个小小的例子解释了为何补码需要原码取反之后再加1,是不是很神奇?

补充知识:java 原码、反码、补码计算 以及 取反(~)运算

1. 原码、反码、补码:

(1)在Java中,所有数据的表示方式都是以补码形式来表示

(2)正数:原码、反码、补码相同

(3)负数:符号位为1,其余各位是对原码取反,然后整个数加1

(4)~按位取反(反码加1称为补码。)步骤就是先求出这个数(因为java存的数是补码)的原码,然后对原码取反得到X,这个X就是我们要求的那个数的补码

2. 取反(~)运算

(1)n=37 ,二进制数就是 100101

因为在Java中,所有数据的表示方式都是以补码形式来表示,如果没有特别的说明,Java 中的数据类型默认为int,int数据类型的长度为4个字节,就是32bit的意思,因此,n=100101的原码=补码(因为是正数,所以原=补=反)运算过程就是:

原码:00000000 00000000 00000000 00100101 =37

~n(对n的原码) 取反运算得: 11111111 11111111 11111111 11011010 很明显,最高位是1,意思是取反后的数字为负数,负数的补码是其绝对值的原码取反,末尾再加1,因此,我们可将这个二进制数的补码进行还原:

首先,末尾减1得反码:11111111 11111111 11111111 11011001

其次,将各位取反得原码:00000000 00000000 00000000 00100110 这个就是~n的绝对值形式,|~n|=38 ,

所以,~n=-38,这个就是Java虚拟机的运算结果

(2)n= - 4, 取反 (~-4)。注意:Java中,所有数据的表示方式都是以补码形式

补码:10000000 00000000 00000000 00000100 (java所有数据的表示方式都是以补码形式,所以把-4用二进制表现出来就是某个数的补码,只是我们看到的是-4)

反码:10000000 00000000 00000000 00000011

原码:11111111 11111111 11111111 11111100

对原码取反:00000000 00000000 00000000 00000011 (3)

因为是正数,所以补码等于原码等于反码= 3,所以~-4 = 3

以上这篇Java为什么使用补码进行计算的原因分析就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持我们。

(0)

相关推荐

  • Java位运算知识点详解

    在日常的Java开发中,位运算使用的不多,使用的更多的是算数运算(+.-.*./.%).关系运算(<.>.<=.>=.==.!=)和逻辑运算(&&.||.!),所以相对来说对位运算不是那么熟悉,本文将以Java的位运算来详细介绍下位运算及其应用. 1. 位运算起源 位运算起源于C语言的低级操作,Java的设计初衷是嵌入到电视机顶盒内,所以这种低级操作方式被保留下来.所谓的低级操作,是因为位运算的操作对象是二进制位,但是这种低级操作对计算机而言是非常简单直接,友好高效

  • 为什么阿里要慎重使用ArrayList中的subList方法

    前言 集合是Java开发日常开发中经常会使用到的. 关于集合类,<阿里巴巴Java开发手册>中其实还有另外一个规定: 本文就来分析一下为什么会有如此建议?其背后的原理是什么? subList subList是List接口中定义的一个方法,该方法主要用于返回一个集合中的一段.可以理解为截取一个集合中的部分元素,他的返回值也是一个List. 如以下代码: public static void main(String[] args) { List<String> names = new

  • java中的按位与(&)用法说明

    为什么4&7结果是4 4 的二进制值是 100,7 的二进制值是 111(实际上 Java 在存储两个数到内存时会自动在有效值 100 和 111 之前补 29 个零来达到整数类型的 4 byte 大小,此处为了方便展示就不补全前面的一串零了), & 是将两数进行位与位的 and 操作(0 & 1 = 0,1 & 1 = 1),所以操作步骤就是 4: 1 0 0 & & & 7: 1 1 1 ---------- = 1 0 0 可见最后得出的结果是

  • Java为什么使用补码进行计算的原因分析

    我们主要要解决的问题就是负数的表示,而众所周知,绝对值相等的两个正负数之和为0. 假设我们有正数 0000 0000 0000 1111,我们如何表示其相反数呢?一般我们的思路是,找一个数,跟它相加的结果等于0,但是我们发现,要找出一个与它相加后结果等于0的数还是要略加思考一下的(因为要计算进位),所以,为何不找出一个与它相加后结果是1111 1111 1111 1111的数,然后该数+1即是我们所要的答案啦. 于是,很容易的, 0000 0000 0000 1111 + 1111 1111 1

  • Java中ThreadLocal 导致内存 OOM 的原因分析

    目录 原因分析 正确的使用方式 原因分析 ThreadLocal 导致内存 OOM 的原因是什么? ThreadLocal 底层通过 ThreadLocalMap 存储数据 源码如下:  当我们使用ThreadLocal.set()时,set的value与key(即业务自己定义的ThreadLocal类)会存储在ThreadLocalMap的Entry[]数组里 源码如下: 其中Entry是实现了一个弱引用WeakReference,Entry的key(即业务方定义的 ThreadLocal类)

  • Java使用5个线程计算数组之和

    前言 之前写过多线程累加计数,原理跟本篇类似,传送门 累加计数比计算数组之和逻辑稍微简单一点,如果对于这块不熟悉的,可以先看下累加计数. 基本思想已经在之前那篇文章里写过了,这里就直接贴代码了. 这里分别通过自己创建线程来实现功能,还有通过线程池来实现功能.思想都差不多.只是代码写法略有不同.仅供参考. 代码一: 五个线程交替累加计算数组之和,这种方法其实不如单线程直接累加快,因为交替累加需要前一个线程计算的结果. package test; import java.util.concurren

  • Java模拟计算机的整数乘积计算功能示例

    本文实例讲述了Java模拟计算机的整数乘积计算功能.分享给大家供大家参考,具体如下: 计算机计算整数乘积的原理: 实现代码: package math; public class two { /** * Fundamental method * f(n) = O(n^2) * @param a * @param b * @return */ public static int naiveMul(int a,int b){ int x = 0; //判断a中出现1的位置,每当出现1就将b的移位运算

  • Java中关于内存泄漏出现的原因汇总及如何避免内存泄漏(超详细版)

    Android 内存泄漏总结 内存管理的目的就是让我们在开发中怎么有效的避免我们的应用出现内存泄漏的问题.内存泄漏大家都不陌生了,简单粗俗的讲,就是该被释放的对象没有释放,一直被某个或某些实例所持有却不再被使用导致 GC 不能回收.最近自己阅读了大量相关的文档资料,打算做个 总结 沉淀下来跟大家一起分享和学习,也给自己一个警示,以后 coding 时怎么避免这些情况,提高应用的体验和质量. 我会从 java 内存泄漏的基础知识开始,并通过具体例子来说明 Android 引起内存泄漏的各种原因,以

  • Java ArrayList.toArray(T[]) 方法的参数类型是 T 而不是 E的原因分析

    前两天给同事做 code review,感觉自己对 Java 的 Generics 掌握得不够好,便拿出 <Effective Java>1 这本书再看看相关的章节.在 Item 24:Eliminate unchecked warnings 这一节中,作者拿 ArrayList 类中的 public <T> T[] toArray(T[] a) 方法作为例子来说明如何对变量使用 @SuppressWarnings annotation. ArrayList 是一个 generic

  • java根据开始时间结束时间计算中间间隔日期的实例代码

    具体代码如下所述: import java.text.ParseException; import java.text.SimpleDateFormat; import java.util.ArrayList; import java.util.Calendar; import java.util.Date; import java.util.List; public class Test { public static List<String> findDates(String stime,

  • Java 堆内存溢出原因分析

    前言 任何使用过基于 Java 的企业级后端应用的软件开发者都会遇到过这种低劣.奇怪的报错,这些报错来自于用户或是测试工程师: java.lang.OutOfMemoryError:Java heap space. 为了弄清楚问题,我们必须返回到算法复杂性的计算机科学基础,尤其是"空间"复杂性.如果我们回忆,每一个应用都有一个最坏情况特征.具体来说,在存储维度方面,超过推荐的存储将会被分配到应用程序上,这是不可预测但尖锐的问题.这导致了堆内存的过度使用,因此出现了"内存不够&

  • Java实现的贷款金额计算功能示例

    本文实例讲述了Java实现的贷款金额计算功能.分享给大家供大家参考,具体如下: 问题及代码: /* *Copyright (c)2015,西南大学计信院 *All rights reserved. *文件名称:Helloworld.java *作 者:高硕 *完成日期:2015年10月15日 *版 本 号:v1.0 *问题描述:通过年利率等来计算月支付额和支付总额. *程序输入:年利率.时间.金额. *程序输出:月支付额和总支付额. */ package practice_01; import

  • java原码补码反码关系解析

    本文为大家解析了java原码补码反码的关系,供大家参考,具体内容如下 原码:不管源数据是十进制还是十六进制,统统将数字转成二进制形式 反码:把原码的二进制统统反过来,0变成1,1变成0 补码:负数的反码加1,就是负数的补码 例子1: 十进制整数 -5,-5的原码101,-5的反码1,010,-5的补码1,011,  所以,-5的反码是-2,-5的补码是-3,其中前面的"1,",表示正数负数 例子2: 十六进制  -ff9B   原码  11111111111110011011 反码  

随机推荐