计算机数值表示Integer
计算机数值表示&Integer
- 原码 反码 补码
- 为什么在计算机中使用补码
- 将减法转换为加法的正确性证明
- Integer
- Short,Long,Byte
- Double,Float
原文章 计算机数值表示&Integer
在分析Integer类之前,先复习一下在计算机中数值的表示
原码 反码 补码
有符号数在计算机中存储,用数的最高位存放符号, 正数为0, 负数为1
- 原码:原码就是符号位加上真值的绝对值,即用第一个二进制位表示符号(正数该位为0,负数该位为1),其余位表示值。
- 反码:正数的反码与其原码相同;负数的反码是对其原码逐位取反,但符号位除外。
- 补码:正数的补码就是其本身;负数的补码是在其反码的基础上+1
例如: - 2 : 00000010(原码),00000010(反码),00000010(补码)
- -2: 10000010(原码),11111101(反码),11111110(补码)
由补码求源码:
- 如果补码的符号位为“0”,表示是一个正数,所以补码就是该数的原码。
- 如果补码的符号位为“1”,表示是一个负数,求原码的操作可以是:符号位为1,其余各位取反,然后再整个数加1。
为什么在计算机中使用补码
对于计算机而言,加减乘数是最基础的运算, 要设计的尽量简单。我们知道,根据运算法则,减去一个正数等于加上一个负数,所以计算机内部可以只有加法而没有减法,将符号位也参与运算,将减法用加法替代。
补码的优点:
- 可将减法变为加法,省去减法器;
- 修复了原码中0的符号(有 [+0] [-0] 之分)以及存在两个编码(0000 0000 和 1000 0000)的问题,而且还能够多表示一个最低数。
补码的由来
负数的补码时相应的正数取反+1
假如一个数是10000110
,对应的正数是00000110
,该数的补码是:11111010
可以看做是0-num
100000000
-00000110
-----------11111010
1 0000 0000 = 1111 1111 + 1
因此可以将以上分为两个步骤:按位取反,加1
11111111
-00000110
-------------11111001 +111111010
将减法转换为加法的正确性证明
已知:X、Y都为正整数,Z = X - Y = X + (-Y)
证明:Z = X的补码 + (-Y的补码)
X的补码 = X; // 正数的补码为其自身
-Y的补码 = (1111 1111 - Y) + 1; // 负数的补码为除符号位的其它位取反加1
Z = X的补码 + (-Y的补码) = X + (1111 1111 - Y) + 1 = X - Y + 1 0000 0000= X - Y + 0000 0000= X - Y
Integer
佩服Lee Boynton,Arthur van Hoff,Josh Bloch,Joseph D. Darcy
计算机中二进制运算比普通的加减乘除快很多,因此代码中很多使用了位运算,难以阅读,挑选了几个具有代表性的函数分析
2^n-1 是一个神奇的数,在各种场景中都有它的身影,比如hashmap取索引,比如求2^n的mod
Integer具有缓存机制,当然不止是Integer,包括Long,Byte等都具有这种性质
public final class Integer extends Number implements Comparable<Integer> {@Native public static final int MIN_VALUE = 0x80000000;@Native public static final int MAX_VALUE = 0x7fffffff;public static final Class<Integer> TYPE = (Class<Integer>) Class.getPrimitiveClass("int");private final int value;
MIN_VALUE
表示最小值-2^31 ,MAX_VALUE
表示最大值2^32-1
转换进制
public static String toString(int i, int radix) {if (radix < Character.MIN_RADIX || radix > Character.MAX_RADIX)radix = 10;/* Use the faster version */if (radix == 10) {return toString(i);}//int型的数最长32位,加上符号33位char buf[] = new char[33];boolean negative = (i < 0);int charPos = 32;//将所有的数转换为负数,主要是为了统一接下来的计算//如果不这样,负数%radix为负数,正数%radix为正数,需要分两种情况判断//为什么不转换为正数,因为最小的负数-2^31转换为正数会溢出if (!negative) {i = -i;}//开始转换while (i <= -radix) {buf[charPos--] = digits[-(i % radix)];i = i / radix;}buf[charPos] = digits[-i];if (negative) {buf[--charPos] = '-';}return new String(buf, charPos, (33 - charPos));}
转换为无符号进制数,转换为2^shift进制
private static String toUnsignedString0(int val, int shift) {// assert shift > 0 && shift <=5 : "Illegal shift value";//得到除了前导0其他的位数int mag = Integer.SIZE - Integer.numberOfLeadingZeros(val);//得到最大的长度int chars = Math.max(((mag + (shift - 1)) / shift), 1);char[] buf = new char[chars];formatUnsignedInt(val, shift, buf, 0, chars);// Use special constructor which takes over "buf".return new String(buf, true);}static int formatUnsignedInt(int val, int shift, char[] buf, int offset, int len) {int charPos = len;//要转换的进制int radix = 1 << shift;//掩码,永远时2^n-1int mask = radix - 1;//每次得到后shift位,val & mask相当于mod运算!,循环得到结果do {buf[offset + --charPos] = Integer.digits[val & mask];val >>>= shift;} while (val != 0 && charPos > 0);return charPos;}
将一个整数放入字符数值中
static void getChars(int i, int index, char[] buf) {int q, r;int charPos = index;char sign = 0;if (i < 0) {sign = '-';i = -i;}// Generate two digits per iterationwhile (i >= 65536) {q = i / 100;// really: r = i - (q * 100);r = i - ((q << 6) + (q << 5) + (q << 2));i = q;//实际上r是一个100以内的数,一次性可以确定两位,根据DigitOnes和DigitTens两个数组buf [--charPos] = DigitOnes[r];buf [--charPos] = DigitTens[r];}// Fall thru to fast mode for smaller numbers// assert(i <= 65536, i);for (;;) {q = (i * 52429) >>> (16+3);r = i - ((q << 3) + (q << 1)); // r = i-(q*10) ...buf [--charPos] = digits [r];i = q;if (i == 0) break;}if (sign != 0) {buf [--charPos] = sign;}}
求前导0的数量
public static int numberOfLeadingZeros(int i) {// HD, Figure 5-6if (i == 0)return 32;int n = 1;//先判断高16位,再判断8位...类似二分法if (i >>> 16 == 0) { n += 16; i <<= 16; }if (i >>> 24 == 0) { n += 8; i <<= 8; }if (i >>> 28 == 0) { n += 4; i <<= 4; }if (i >>> 30 == 0) { n += 2; i <<= 2; }//判断最高位,若是0,则就是31位,反之30位前导0n -= i >>> 31;return n;}
求低位第一位为1的值
public static int lowestOneBit(int i) {// HD, Section 2-1return i & -i;}
求高为第一位为1的权值
public static int highestOneBit(int i) {// HD, Figure 3-1i |= (i >> 1);i |= (i >> 2);i |= (i >> 4);i |= (i >> 8);i |= (i >> 16);//此时i为11111111...return i - (i >>> 1);}
缓存机制:默认缓存范围是-128~127,因此,两个数值在此区间的Ing=teger使用==
判断返回的是true
,二其他相等范围的Integer则返回false。例如:
Integer c=55;Integer d=55;System.out.println(c==d);(true)Integer e=999;Integer f=999;System.out.println(e==f);(false)
源码:
//私有的静态内部类
private static class IntegerCache {static final int low = -128;static final int high;//使用一个数组存储缓存static final Integer cache[];//静态代码块,在类加载时期就已经执行了static {int h = 127;//用于指定缓冲区的大小String integerCacheHighPropValue =sun.misc.VM.getSavedProperty("java.lang.Integer.IntegerCache.high");if (integerCacheHighPropValue != null) {try {int i = parseInt(integerCacheHighPropValue);i = Math.max(i, 127);// Maximum array size is Integer.MAX_VALUEh = Math.min(i, Integer.MAX_VALUE - (-low) -1);} catch( NumberFormatException nfe) {// If the property cannot be parsed into an int, ignore it.}}high = h;cache = new Integer[(high - low) + 1];int j = low;for(int k = 0; k < cache.length; k++)cache[k] = new Integer(j++);assert IntegerCache.high >= 127;}private IntegerCache() {}}
//如果数值在缓存范围,获取的就是缓存的对象,而非重新new
public static Integer valueOf(int i) {if (i >= IntegerCache.low && i <= IntegerCache.high)return IntegerCache.cache[i + (-IntegerCache.low)];return new Integer(i);}
Short,Long,Byte
这些类与Integer相似,只是范围不同,它们也有缓存机制,范围都是-128~127,并且不可更改
Double,Float
注意:是允许1/0,-1/0,0/0的,其他类型都不允许
例如:
Double a=-1.0/0.0+100;Double b=1.0/0.0;Double c=0.0/0.0;System.out.println(a); ( -Infinity )System.out.println(b); ( Infinity )System.out.println(c); ( NaN )
借鉴了你真的了解补码吗
计算机数值表示Integer相关推荐
- Pandas把dataframe中的整数数值(integer)转化为时间(日期、时间)信息实战
Pandas把dataframe中的整数数值(integer)转化为时间(日期.时间)信息实战 目录 Pandas把dataframe中的整数数值转化为时间(日期.时间)信息实战
- 计算机数值中的乘法除法原理
乘法:被分解为左移累加. 除法:被分解为右移累减去,减法可以转换为加法. 浮点数的运算: S x 2(^F) x M 浮点数是原码表示法,S符号位,F阶码 + 127, M尾数舍弃前面的1(如果F&l ...
- 计算机数值仿真及虚拟现实论文,计算机仿真论文- 计算机仿真技术及其发展.doc...
计算机仿真技术及其发展 一.引言: 作为信息技术核心的计算机技术自其诞生之日起经历了50多年的发展,以广泛应用于国民经济和社会生活中.而作为计算机技术重要组成部分的计算机三维视景仿真技术,因其有效性. ...
- 数值计算方法计算机,数值计算方法
常见"问题" 1.如何认识数值计算课程?它与数学学科的其它分支以及计算机的关系如何? 2.何为算法?如何判断数值算法的优劣? 3.数值计算方法中最关注哪些误差?为什么? 4.什么是 ...
- 计算机数值数据的编码,计算机数值数据编码(原码,反码,补码,移码)
机器数有无符号数和带符号数之分.无符号数表示正数,在机器数中没有符号位.对于无符号数,若约定小数点的位置在机器数的最低位以后,则是纯整数:若约定小数点的位置在机器数的最高位以前,则是纯小数.对于带符号 ...
- 计算机数值类型的数据为什么以补码表示,计算机为什么使用补码来存储数据
计算机为什么使用补码来存储数据 说明:以下讨论,都是用8位来存储的数据类型:char类型, 为什么?为什么用补码呢?我反复思考着,后来在王爽的汇编语言里和网上找到了答案,有如下总结: 原码表示的数: ...
- 利用计算机进行数值模拟计算,数值模拟法
差分法 差分法是把原来求解物体内随空间.时间连续分布的温度问题,转化为求在时间领域和空间领域内有限个离散点的温度值问题,再用这些离散点上的温度值去逼近连续的温度分布.差分法的解题基础是用差商来代替微商 ...
- 【计算机英语词汇和词组-持续更新中】
推荐词典:有道词典 理由:在看外文网站的时候,可以实现 取词和划词翻译 这是 在看外文网站的时候,一点点 记录的学习笔记,归纳后方便记忆 按照 首字母顺序排列 备注的发音音标,都是美式的发音 持续更新 ...
- 计算机仿真的过程,计算机仿真的过程与方法.doc
<通信系统仿真> 实验报告 姓名杨利刚班级A0811实验室203组号28学号28实验日期实验名称实验一 计算机仿真的过程与方法实验成绩教师签字一.实验目的 1.掌握计算机仿真的一般过程 2 ...
最新文章
- android git提交整个项目_使用git管理嵌入式软件版本
- SPOJ 27020 	GST Calculator
- 解决packet tracer不能复制CLI内容的问题
- Javascript中的valueOf与toString
- 3.8 高级检索方式(二)
- P5371-[SNOI2019]纸牌【矩阵乘法】
- mybatis oracle trim,Mybatis trim标签
- bzoj 4548: 小奇的糖果 bzoj 3658: Jabberwocky(双向链表+树状数组)
- CorelDRAW2021版本下载 百度网盘
- 对于目标文件系统,文件过大放不到U盘里
- 《SEM长尾搜索营销策略解密》一一1.5 互联网时代,世界不再匮乏
- 计算几何之多边形重心
- wxs 实现小程序拖拽功能
- 相似度度量的不同方法
- python虚拟机管理系统_python 虚拟机 pdf
- H3C无线网络优化指导——经验之谈
- ppt转.exe文件小技巧(超链接含视频)
- sap中如何追踪生产订单的修改记录
- JS与jQuery获取任意事件的子元素下标(获取当前类数组的某一子元素下标)
- 一文读懂Tiger DAO VC模式,风险投资改朝换代
热门文章
- 中欣晶圆完成B轮33亿元融资;晶科能源与宁德时代达成战略合作 | 美通社头条...
- 使用微信小程序拨打电话
- Traefik v2.9-IngressRoute
- css3滤镜属性filter实现网页变黑白效果
- 抖音SEO,抖音SEO搜索排名详细介绍
- 解决开发qq音乐singer-detail组件时子路由跳转失败问题
- 蜘蛛爬行html语言的顺序,SEO优化 蜘蛛的爬行规则以及让蜘蛛爬行的快速办法
- scala 中 foreach 的作用解释
- 安卓系统的电视机_换机顶盒比换电视机划算,海美迪4K播放器H7 Plus体验
- 最好的vsftpd配置教程