计算机数据存储原理及类型转换

本文详细介绍了计算机存储数据的基础概念,如比特、字节、存储单位以及Java中基本数据类型的宽度。重点讲解了符号位、原码、反码和补码的概念,并通过实例演示了整数和小数的存储方式,以及不同类型数据之间的转换规则,包括自动类型转换和强制类型转换。同时提及了ASCII和Unicode字符集在char类型数据存储中的应用。
摘要由CSDN通过智能技术生成

一、计算机存储数据的原理(理解)

1.1 存储单位是什么

1、最小单位:比特,bit,1个二进制位

例如:boolean值就可以用1个比特位来表示,true用1表示,false用0表示。

2、最基本单位:字节,byte,1个字节有8个二进制位

  • 1B=8位

  • 1KB=1024B

  • 1MB=1024KB

  • 1GB=1024MB

  • 1TB = 1024GB

  • 1PB = 1024TB

10月24日:程序员节

扩展:网络带宽:100Mb,此时的b是bit。

1.2 Java的8种基本数据类型的宽度(要记几个字节)

1.3 符号位、原码、反码、补码(理解)

1、符号位

是指二进制序列的最高位,最左边的位。0表示正数,1表示负数。

2、原码、反码、补码

为了让符号位也参与运算,负数就必须要转为补码表示。

正数:原码、反码、补码都一样,不区分。

例如:25   以1个字节的宽度为例
    原码:00011001
    反码:00011001
    补码:00011001

负数:原码、反码、补码都不一样。

例如 -25
    原码:10011001
    反码:11100110               在原码基础上,符号位不变,其余位取反,1变0,0变1
    补码:11100111               在反码基础上+1

计算机底层的存储和计算都是基于补码计算的。

3、练习

列出如下几个数字的原码、反码、补码,统一用4个字节(int)

160, -250, 1024, -963
    
    160:
        正数:原码、反码、补码都一样
        原码:00000000 00000000 00000000 10100000
        反码:00000000 00000000 00000000 10100000
        补码:00000000 00000000 00000000 10100000
   -250:
        负数:原码、反码、补码都不同
        补码:11111111 11111111 11111111 00000110   
        反码:11111111 11111111 11111111 00000101    在补码基础上-1得到反码
        原码:10000000 00000000 00000000 11111010    符号位不变,其余位取反
    
            如果要人工算 二进制->十进制, 一定要基于原码算。
                    (1)最高位是符号位,1是负数的意思
                    (2)其余位加权值 128 + 64 + 32 + 16 + 8 + 2 = 250
            如果要计算器算 二进制->十进制, 一定要基于补码算。
                

4、练习

将如下二进制补码对应的十进制算出来。

11100111
00000000 00000000 00000011 01010010
01100110
11111111 11111111 11111111 11111011

答案:-25,850,102,-5

1.4 1个字节如果用来存储整数的多大值(-128~127)

1个字节:
    符号位是0的时候:
    最小的二进制补码:00000001       十进制:1
    最大的二进制补码:01111111       十进制:127
    
    符号位是1的时候:
    最小的二进制补码:10000001       十进值:-127   如果用计算器算,粘的是补码
              反码:10000000
              原码:11111111                     如果是人工口头算,用原码算,最高位代表负数,其余位权值相加:64+32+16+8+4+2+1
    
    特殊的两个值:
            00000000               十进制:0
            10000000               十进制:-0没有意义,不用它来表示负0
                                        用它来表示-128
    
    首先,最高位是1,代表是负数。
    其次,需要满足计算规则
        -127-1 = 用补码算
        -127的补码:10000001
        1的补码:   00000001
        相减-----------------
                   10000000    数学中它是-128,计算器算出来也得是-128

1.5 char类型的数据怎么存储呢(char有编码值,有几种表示方式)

为了在计算机底层也能存储字符:包括字母、标点符号、汉字等,那么一些协会在一起指定了一些标准,最早生成了一个ASCII字符集。这个字符集中为每一个字符规定了一个整数值,它被称为编码值。例如:'0'的编码值是48,'1'的编码值是49,依次类推。'A'的编码值是65,'B'的编码值是66,依次类推。'a'的编码值是97,'b'的编码值是98,依次类推。

ASCII不支持中文等其他字符。计算机要流传到其他国家时,就无法表示其他国家的字符了。

后来逐步延后,到了今天有一个万国码字符集,就是Unicode字符集,它里面包含了所有国家的常用字符,一共65536个字符,编码值范围是[0,65535]。Unicode字符集是兼容ASCII字符集。

char类型的数据在程序中的表示方式有如下几种:

  • 单引号,里面直接写字符本身

  • 用十进制的Unicode编码值

  • 单引号,里面写\u4位的十六进制编码值

public class CharDemo{
    public static void main(String[] args){
        /*
        System.out.println('0' + 1 );//49
                          //char + int
        System.out.println(0 + 1 );//1
                          //int  + int
                            */
        char aLetter1 = 'a';
        char aLetter2 = 97; //十进制编码值
        char aLetter3 = '\u0061'; //十六进制编码值  \u,表示是Unicode编码值
        System.out.println(aLetter1);
        System.out.println(aLetter2);
        System.out.println(aLetter3);
        
    }
}

还有几个特殊的char,它们需要转义:

  • \t:制表符,键盘上的Tab

  • \n:换行符

  • \r:回车符,本行结束符

  • \b:退格键,键盘上Backspace

  • \\:斜杆本身

  • \":双引号

  • \':单引号

public class CharDemo2{
    public static void main(String[] args){
        char c1 = '\'';
        System.out.println(c1);
        char c2 = '"';
        System.out.println(c2);
        
        String s1 = "\"";
        System.out.println(s1);
        
        String s2 = "'";
        System.out.println(s2);
        
        char c3 = '\\';
        System.out.println(c3);
        
        String s3 = "\\";
        System.out.println(s3);
    }
}
public class CharDemo3{
    public static void main(String[] args){
        System.out.println("hello\tworld\tjava");
        System.out.println("hello\b\bworld\b\bjava");
        System.out.println("hello\rworld\rjava");
        System.out.println("hello\nworld\njava");
    }
}
public class CharDemo4{
    public static void main(String[] args){
        System.out.println("hello\tworld\tjava.");
        System.out.println("chailinyan\tis\tbeautiful.");
        System.out.println("姓名\t基本工资\t年龄");
        System.out.println("张三\t10000.0\t23");
    }
}

1.6 小数类型的数据怎么存储(记3个结论)

小数类型的存储比前面那些类型都复杂,大家不用过多的研究。下面先抛出结论,再做简单的简绍:

  • 无论是float还是double都是==不精确==,因为不是每一个小数都有一个唯一的二进制来表示它的

  • float类型虽然是4个字节,double类型是8个字节,它们都==比long类型的存储范围要大==。因为小数的底层会存储符号位、指数位、尾数位。

  • ==double类型比float类型的精度范围更大一些==

    • double类型大约能表示到科学记数法的小数点后15~16位

    • float类型大约能表示到科学记数法的小数点后6~7位

    • 后面会学习BigDecimal类型,处理任意精度的小数

public class FloatDoubleDemo{
    public static void main(String[] args){
        float f = 3.14159265685781234F;
        double d = 3.14159265685781234;
        System.out.println(f);//3.1415927
        System.out.println(d);//3.1415926568578123
    }
}

以:8.2为例说明它的存储原理

第一步:8.2转为二进制

整数部分8:除2倒取余,得到1000
小数部分0.2:乘2取整数 得到: 00110011........

第二步:把上述二进制值转为科学计数法

科学计数法:整数部分只有1位非零的数字,其余都挪到小数点后面。

8.2 的二进制  1000.00110011........  
  科学计数法: 1.00000110011........ * 2的3次方
    

这么挪的原因是因为底层不想保存和处理小数点。

所有二进制用科学计数法表示之后,有一个共同特点:整数部分都是1,这样的话,就不用表示小数点了,也不用表示整数部分了。

第三步:需要表示符号位、指数位、尾数位

  • 符号位:最高位,0是正数,1是负数

  • 指数位:本例中指数值是3,3可以用二进制表示 00000011

    • float类型的指数位占8位

    • double类型的指数位占11位

  • 尾数位:小数点后面的所有二进制位就是尾数位

二、基本数据类型的转换问题(掌握)

boolean不参与任何转换。

1、自动类型转换

  • 方向:

    • byte->short->int->long->float->double

    • char->

  • 当把存储范围小的类型的值 赋值 给存储范围大的类型的变量时,会自动类型提升。

public class DataTypeChangeDemo1{
    public static void main(String[] args){
        int num = 'a';
        System.out.println(num);
        /*
        'a'是char类型,num是int类型,把char类型转为int类型
        */
        
        double d = 5;
        System.out.println(d);
        /*
        5是int类型,d是double,把int类型转为double类型
        */
        
        double d2 = 'a';
        System.out.println(d2);
    }
}
  • 当byte与byte,short与short,char与char,或者它们3个之间的计算,会自动升级为int(特殊)

public class DataTypeChangeDemo2{
    public static void main(String[] args){
        byte b1 = 1;
        byte b2 = 2;
        //byte b3 = b1 + b2;
        /*
            b1 + b2结果3已经是int类型
            int类型存储范围 > byte类型存储范围
        */
        //System.out.println(b3);
        
        System.out.println(b1+b2);
        
        short s1 = 1;
        short s2 = 2;
        //short s3 = s1 + s2;
        System.out.println(s1+s2);
        
        char c1 = '0';
        char c2 = '1';
        System.out.println(c1+c2);
        //char c3 = c1+c2;
        
    }
}
  • 当多种类型混合运算时,结果是它们中最大的类型

public class DataTypeChangeDemo3{
    public static void main(String[] args){
        System.out.println(1 + 'a' + 15L + 1.0);
        //                int + char + long + double 结果是double
    }
}

2、强制类型转换

方向:

  • double->float->long->int->short->byte

  • ->char

  • 当把存储范围大的类型的值 赋值给存储范围小的类型的变量时,就必须使用强制类型转换。这种转换有风险,可能损失精度,可能溢出。

public class DataTypeChangeDemo4{
    public static void main(String[] args){
        double d = 1.5;
        int i = (int)d;//当把d里面的1.5赋值给i时,强制把1.5转为int类型
        System.out.println(i);//损失精度
        
        int x = 1;
        int y = 2;
        System.out.println(x/y);//按照数学是0.5,强制把0.5转为int类型,结果是0
        System.out.println((double)x/y);
        /*
        这里先把x强制升级为double  1变为1.0,
        然后再计算 1.0 / 2 ,混合运算都升级为double  1.0 / 2.0 结果是0.5
        */
        
        byte b1 = 127;
        byte b2 = 2;
        byte b3 = (byte)(b1 + b2);
        System.out.println(b3);//-127
        /*
        127+2的结果129
        129是int类型的话 00000000 00000000 00000000 10000001(补码)
        强制转为byte类型 截断,只留下最后一个字节    10000001(补码)
        
        */
    }
}

3、练习题

1、练习题:判断如下代码是否编译通过,如果能,结果是多少?
short s1 = 120;
short s2 = 8;
short s3 = s1 + s2;
​
s1+s2是short+short,结果自动升级为int,
    int比short大,编译失败
​
2、练习题:判断如下代码是否编译通过,如果能,结果是多少?
short b1 = 120;
short b2 = 8;
byte b3 = (byte)(b1 + b2);//-128
​
b1 + b2得到int的结果是128,然后强制类型转换
    int类型的128的二进制 00000000  00000000 00000000 10000000  补码
    然后强制类型转换,发生截断,只保留1个字节  10000000         补码
    对应-128
​
​
3、练习题:判断如下代码是否编译通过,如果能,结果是多少?
char c1 = '0';
char c2 = '1';
char c3 = c1 + c2;
​
c1+c2是char+char,,结果自动升级为int,
    int比char大,编译失败
​
4、练习题:判断如下代码是否编译通过,如果能,结果是多少?
char c1 = '0';
char c2 = '1';
System.out.println(c1 + c2);
​
c1+c2是char+char,,结果自动升级为int.
    println可以支持各种类型的数据的输出,可以输出int值,结果是97
    '0'的编码值是48,'1'的编码值是49
​
5、练习题:判断如下代码是否编译通过,如果能,结果是多少?
int i = 4;
long j = 120;  
double d = 34; 
float f = 1.2;
System.out.println(i + j + d + f);  
​
float f = 1.2;报错,因为1.2是double类型,要表示float类型必须加F或f
​
6、练习题:判断如下代码是否编译通过,如果能,结果是多少?
int a = 1;
int b = 2;
double result = a/b;
System.out.println(result);
​
a/b是int/int,结果是0
0又赋值给double,又升级为0.0
评论 1
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值