JAVA的枚举基本操作,对原码反码补码的理解及为运算的深入理解,浮点数计算的误差分析
①深入浅出的了解枚举类型
先看一段代码:
enum Size{SMALL,MEDIUM,LARGE};
public class EnumTest {
    public static void main(String[] args) {
        Size s=Size.SMALL;
        Size t=Size.LARGE;
        //s和t引用同一个对象?
        System.out.println(s==t);  //false
        //是原始数据类型吗?
        System.out.println(s.getClass().isPrimitive());//false
        //从字符串中转换
        Size u=Size.valueOf("SMALL");
        System.out.println(s==u);  //true
        //列出它的所有值
        for(Size value:Size.values()){
            System.out.println(value);//顺序输出枚举类的值
        }
    }
}
首先我们定义了一个枚举类Size,在主函数中定义了两个对象,分别赋值为SMALL和LARGE
首先判断的是他们是否为同一个对象?结果:FALSE
第二个输出的是他是原始的数据类型吗?结果:FALSE
第三个通过将一个普通的字符串转换成一个枚举对象,然后在判断他是否与初始定义的枚举对象相同?结果:TRUE
第四个通过一个foreach语句,和枚举的一个方法values()实现将枚举类型成员以数组的形式返回,然后按顺序输出枚举成员的值。
通过以上的程序事例,让我们了解到,枚举类型属于引用类型,每个具体的值都引用特定的对象,相同的值引用的是同一个对象,就像s==u一样。
枚举类型还有个方法:ordinal()用来得到枚举成员的索引,例如上个代码中的:System.out.println(t.ordinal());结果为:2
还可以比较两个枚举对象在定义时的顺序:compareTo(),例如:Size q=Size.MEDIUM; System.out.println(q.compareTo(t)); 结果为:-1,因为q对象的值要小于t对象的值,用它两下标相减。
除此之外:还可以在枚举类型中添加新的方法
enum Color {
    RED("红色", 1), GREEN("绿色", 2), BLANK("白色", 3), YELLO("黄色", 4);
    // 成员变量
    private String name;
    private int index;
    // 构造方法
    private Color(String name, int index) {
        this.name = name;
        this.index = index;
    }
    // 寻找下标对应的名字
    public static String getName(int index) {
        for (Color c : Color.values()) {
            if (c.getIndex() == index) {
                return c.name;
            }
        }
        return null;
    }
    // get set 方法
    public String getName() {
        return name;
    }
    public void setName(String name) {
        this.name = name;
    }
    public int getIndex() {
        return index;
    }
    public void setIndex(int index) {
        this.index = index;
    }
}
public class Enum {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        Color a=Color.RED;
        System.out.println(Color.getName(2));
        System.out.println(a.getName()+" "+a.getIndex());
    }
}
在枚举类型中添加私有数据:index和name还添加了寻找下标所对应的名字的方法,在主函数中调用枚举类,实现新方法。
输出为:
绿色
红色 1
②原码,反码,补码
原码:是最简单的机器数表示法。用最高位表示符号位,‘1’表示负号,‘0’表示正号。其他位存放该数的二进制的绝对值。
举个简单的栗子:
0101,其最高位为‘0’,证明他首先是正数,其次再用二进制的方法来计算它 sum=1*22+0*21+1*20=6,因此该二进制数代表的就是6
1111,其最高位为‘1’,证明他首先是负数,其次再用同样的方式来计算 sum=-(1*22+1*21+1*20)=-7,因此该二进制数代表的就是-7
 该表可以帮助你进一步的理解原码
该表可以帮助你进一步的理解原码
反码:正数的反码还是等于原码,负数的反码就是他的原码除符号位外,其他位取反(例如:如果原先是1->0,原先是0->1)
例如:-5所对应的二进制数是:1101 他的反码就是:1010
给一些数的反码来进行观察

补码:正数的补码等于他的原码,负数的补码等于他的反码+1,符号位不变
例如:-5的二进制数是:1101 反码:1010 补码:1011

说完基本的概念后,我们来看一下一些数,位运算是如何计算的:按位与&,按位或|,按位取反~,按位异或^
按位&:如果两个数的对应位都为1,结果才为1.
public class ma {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int a=4,b=5;
        System.out.println(a&b);
    }
}
猜一猜结果为多少:4.
如果两个数为一正一负呢?
public class ma {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int a=2,b=-5;
        System.out.println(a&b);
    }
}
你的答案是不是:0,恭喜你答错了,实际输出的是:2.
为什么呢?因为在计算机中正数的原码,反码,补码都是一样的,而负数的却是不一样的,为了能够实现减法的运算,在JAVA中所有的数都是用补码来存储的。
不信,咱们可以算算。
2 补码:0010
-5 原码:1101 反码:1010 补码:1011
0010&1011=0010 该结果为2,答案正确。
按位或:两个操作数中对应位都是0,结果才是0,否则为1.
public class ma {
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int a=2,b=-5;
        System.out.println(a|b);
    }
}
大家想一想这个数是多少?
答案是:-5
2 补码:0010
-5 原码:1101 反码:1010 补码:1011
0010|1011=1011 1011看符号位是‘1’,证明他是个负数,而负数都是以补码的形式来存放的,因此,我们要给他还原回去
1011 ->1010 ->1101 结果为:-5 答案正确
按位取反:~就是将操作数二进制的1修改为0,0修改为1
按位异或:^当两个操作数的二进制位表示相同时为0,否则为1
③字符串连接的小常识
public class Test {
public static void main(String[] args) {
        int X=100;
    int Y=200;
    System.out.println("X+Y="+X+Y);
    System.out.println(X+Y+"=X+Y");
    }
}
输出:
X+Y=100200
300=X+Y
字符串与变量相+时,就会形成一个新的字符串
先进行变量的相+时,则会先进行数值相加,然后再连接字符串
④同名变量的屏蔽原则
每个变量都有一个“有效的”区域,出了该区域,变量就不再有效。
例如:
package com.大数计算;
public class xiaoce {
static int a=10;
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int a=5;
        System.out.println(a);
    }
}
输出:5
package com.大数计算;
public class xiaoce {
static int a=10;
static void f()
{
    int a=0;
    System.out.println(a);
}
    public static void main(String[] args) {
        // TODO Auto-generated method stub
        int a=5;
        f();
        System.out.println(a);
    }
}
输出:0 5
在f()方法里,a的有效范围就是f()方法,故输出0
⑤double类型的运算精确吗?
package com.大数计算;
public class TestDouble {
    public static void main(String args[]) {
        System.out.println("0.05 + 0.01 = " + (0.05 + 0.01));//尾数不一样
        System.out.println("1.0 - 0.42 = " + (1.0 - 0.42));
        System.out.println("4.015 * 100 = " + (4.015 * 100));
        System.out.println("123.3 / 100 = " + (123.3 / 100));//.3
        System.out.println(12.3/100);
    }
}
0.05 + 0.01 = 0.060000000000000005
1.0 - 0.42 = 0.5800000000000001
4.015 * 100 = 401.49999999999994
123.3 / 100 = 1.2329999999999999
0.12300000000000001
为什么会出现这样的误差?
其根本原因是计算机所使用二进制01代码无法准确表示某些带小数位的十进制数据。
那我们应该如何解决这样的误差问题呢?
于是,引入math.BigDecimal;
package com.大数计算; import java.math.BigDecimal;
//浮点数是不精确的
public class TestBigDecimal
{
public static void main(String[] args)
{
BigDecimal f1 = new BigDecimal("0.05");
BigDecimal f2 = BigDecimal.valueOf(0.01);
BigDecimal f3 = new BigDecimal(0.05);
System.out.println("下面使用String作为BigDecimal构造器参数的计算结果:");
System.out.println("0.05 + 0.01 = " + f1.add(f2));
System.out.println("0.05 - 0.01 = " + f1.subtract(f2));
System.out.println("0.05 * 0.01 = " + f1.multiply(f2));
System.out.println("0.05 / 0.01 = " + f1.divide(f2)); System.out.println("下面使用double作为BigDecimal构造器参数的计算结果:");
System.out.println("0.05 + 0.01 = " + f3.add(f2));
System.out.println("0.05 - 0.01 = " + f3.subtract(f2));
System.out.println("0.05 * 0.01 = " + f3.multiply(f2));
System.out.println("0.05 / 0.01 = " + f3.divide(f2));
}
}
下面使用String作为BigDecimal构造器参数的计算结果:
0.05 + 0.01 = 0.06
0.05 - 0.01 = 0.04
0.05 * 0.01 = 0.0005
0.05 / 0.01 = 5
下面使用double作为BigDecimal构造器参数的计算结果:
0.05 + 0.01 = 0.06000000000000000277555756156289135105907917022705078125
0.05 - 0.01 = 0.04000000000000000277555756156289135105907917022705078125
0.05 * 0.01 = 0.0005000000000000000277555756156289135105907917022705078125
0.05 / 0.01 = 5.000000000000000277555756156289135105907917022705078125
将double类型转换成String类型,在进行运算就可以保证数值的精确,切记不要使用double类型去初始化BigDecimal对象,会产生误差。
JAVA的枚举基本操作,对原码反码补码的理解及为运算的深入理解,浮点数计算的误差分析的更多相关文章
- JAVA:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题(5)
		一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ... 
- Java学习第五篇:二进制(原码 反码 补码),位运算,移位运算,约瑟夫问题
		一.二进制,位运算,移位运算 1.二进制 对于原码, 反码, 补码而言, 需要注意以下几点: (1).Java中没有无符号数, 换言之, Java中的数都是有符号的; (2).二进制的最高位是符号位, ... 
- Java基础-原码反码补码
		Java基础-原码反码补码 作者:尹正杰 版权声明:原创作品,谢绝转载!否则将追究法律责任. 注意,我们这里举列的原码和反码只是为了求负数的补码,在计算机中没有原码,反码的存在,只有补码. 一.原码 ... 
- java原码反码补码以及位运算
		原码, 反码, 补码的基础概念和计算方法. 对于一个数, 计算机要使用一定的编码方式进行存储. 原码, 反码, 补码是机器存储一个具体数字的编码方式. 1. 原码 原码就是符号位加上真值的绝对值, 即 ... 
- java基础知识-原码,反码,补码
		1.正数:原码,反码,补码:都一样. 2.负数:和正数的储存方式不同,负数都是以补码形式存储的. <1>负数的补码 把负数的原码除了符号位取反后再+1. <2>负数的原码 把对 ... 
- Java 原码 反码 补码
		本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希 ... 
- 位移&二进制转换&原码&反码&补码
		<< 左移 按二进制形式把所有的数字向左移动对应的位数,高位移出(舍弃),低位的空位补零. 格式 需要移位的数字 << 移位的次数 计算过程 1. 按二进制形式把所有的数字向左 ... 
- 原码 & 反码 & 补码 & 详解
		本篇文章讲解了计算机的原码, 反码和补码. 并且进行了深入探求了为何要使用反码和补码, 以及更进一步的论证了为何可以用反码, 补码的加法计算原码的减法. 论证部分如有不对的地方请各位牛人帮忙指正! 希 ... 
- C语言原码反码补码与位运算.
		目录: 一.机器数和真值 二.原码,反码和补码的基础概念 三.为什么要使用原码,反码和补码 四.原码,补码,反码再深入 五.数据溢出测试 六.位运算 ... 
- python之计算机硬件基本认知_数据单位_进制间转换_数的原码反码补码
		一:计算机硬件基本认知 cpu: 中央处理器. 相当于人的大脑.运算中心,控制中心. 内存: 临时存储数据. 优点:读取速度快,缺点:容量小,造价高,断电即消失. 硬盘: 长期存储数据. ... 
随机推荐
- PKUWC2019 Round 2 没去祭
			因为今年有两场 PKUWC,所以叫 PKUWC2019 Round 2. 因为一些沙雕原因,今年去不了了. Day 0 一如既往,没有集训就去上数学课,今天讲几何变换,一如既往的只会说"少女 ... 
- SPA和MVVM设计思想
			Vue基础篇设计模式SPAMVVMVue简介Vue的页面基本使用Vue的全局环境配置基本交互 插值表达式基础指令 v-text v-html v-pre v-once v-cloak v-on MVV ... 
- 2016级移动应用开发在线测试12-service
			有趣有内涵的文章第一时间送达! 喝酒I创作I分享 生活中总有些东西值得分享 @醉翁猫咪 1. Service是Android系统中的四大组件之一(Acitivty.Service.ContentPr ... 
- nRF51822 主从断开连接Reason,HCI ERROR CODE :0x003E
			最近在给一个客户调主从一体的模块,基于S130,距离稍微远一点就会出现连接上后立马又断开连接的现象, 追踪了一下原因,给出的 HCI Error code 是 0x003E,暂且不知道这是什么鬼,查了 ... 
- Echarts的简单入门
			5 分钟上手 ECharts 获取 ECharts 你可以通过以下几种方式获取 ECharts. 从官网下载界面选择你需要的版本下载,根据开发者功能和体积上的需求,我们提供了不同打包的下载,如果你在体 ... 
- Tcl条件语句
			If {条件表达式1} { 执行语句1 } elseif {条件表达式2} { 执行语句2 } elseif {条件表达式3} { 执行语句3 } else { 执行语句4 } 注:elseif {条 ... 
- [代码质量]  Git统计本次提交新增代码行数,建议每个评审commit新增行数小于400行
			git log HEAD~1..HEAD --author="$(git config --get user.name)" --pretty=tformat: --numstat ... 
- 解决VS Code开发Python3语言自动补全功能
			1.打开设置界面 2)使用快捷键组合[Ctrl+Shift+p] . 输入setting,选中首选项的user setting模式设置界面 在打开的User Settings文件界面,搜索:pytho ... 
- LeetCode_437. Path Sum III
			437. Path Sum III Easy You are given a binary tree in which each node contains an integer value. Fin ... 
- (转)自动微分(Automatic Differentiation)简介——tensorflow核心原理
			现代深度学习系统中(比如MXNet, TensorFlow等)都用到了一种技术——自动微分.在此之前,机器学习社区中很少发挥这个利器,一般都是用Backpropagation进行梯度求解,然后进行SG ... 
