Java-Day-4(进制 + 三大流程控制语句)

发布时间 2023-04-04 23:47:12作者: 朱呀朱~

Java-Day-4

进制

整数

  1. 二进制:0,1,满二进一,0b 或 0B开头
  2. 十进制:0 ~ 9,满十进一
  3. 八进制:0 ~ 7,满八进一,数字 0 开头
  4. 十六进制:0 ~ 9 及 A / a ( 10 ) ~ F / f ( 15 ),满十六进一,0x 或 0X 开头
十进制 十六进制 八进制 二进制
9 9 11 1001
10 A 12 1010
11 B 13 1011
12 C 14 1100
13 D 15 1101
14 E 16 1110
15 F 17 1111
16 10 20 10000
17 11 21 10001

进制转换

  • 被转为十进制

    1. 二进制转十进制:从最低位 ( 右 ) 开始,将每个位上的数提取出来,乘 2 ^ ( 位数 - 1 ) ,然后求和

      • 例:0b1011 = 1 * 2 ^ 0 + 1 * 2 ^ 1 + 0 * 2 ^ 2 + 1 * 2 ^ 3

        ​ = 1 + 2 + 8

        ​ = 11

    2. 八进制转十进制:似上,改为乘 8 ^ ( 位数 - 1 )

      • 例:0234 = 4 + 3 * 8 + 2 * 64 = 156
    3. 十六进制转十进制:似上,改乘 16 ^ ( 位数 - 1 )

      • 例:0x23A = 10 + 3 * 16 + 2 * 256 = 570
  • 十进制转换为

    1. 十进制转换为二进制:将数不断除以 2,直到商为 0 为止,然后将每次得到的余数倒过来即可

      • 例:34 = 0B00100010 ( 100010 — 0B100010 — 0B00100010 )

        ​ —> 一个字节是存储的基本单位,一个字节有八位,不够的 0 补

        除数 被除数 余数
        2 34 ( 倒写此列 )
        2 17 0
        2 8 1 ( 17 / 2 = 8 ... 1 )
        2 4 0
        2 2 0
        2 1 0
        1 ( 1 / 2 = 0 ... 1 )
    2. 十进制转换为八进制:似上,改为除以 8

      • 例:131 = 0203

        除数 被除数 余数
        8 131
        8 16 3
        8 2 0
        2
    3. 十进制转换为十六进制:似上,改为除以 16

      • 例:237 = 0xED

        除数 被除数 余数
        16 237
        16 14 D ( 13 )
        E ( 14 )
  • 二进制转换为

    1. 二进制转换为八进制:从低位开始,二进制数每三位一组,转成对应的八进制数即可
      • 例:0b11010101 = ( 0b 11 010 101 ) = 0325
    2. 二进制转换成十六进制:似上,改为二进制数每四位一组
      • 例:0b11010101 = ( 0b 1101 0101 ) = 0xD5
  • 八进制转换为

    1. 八进制转换为二进制:将八进制每一位数转换成对应的一个三位的二进制数
      • 例:0237 = ( 010 011 111 = 0b 0 1001 1111 ) = 0b10011111
  • 十六进制转换为

    1. 十六进制转换为二进制:将十六进制每一位数转换成对应的四位的二进制数
      • 例:0x23B = ( 0x 0010 0011 1011 ) = 0b001000111011
  • 计算器中:BIN 二进制;OCT 八进制;DEC 十进制;HEX 十六进制

位运算

计算机内部处理的信息都是采用二进制数来表示的

原码、反码、补码

  1. 二进制的最高位 ( 最左边 ) 是符号位,0 表整数,1 表负数
  2. 正数的原码、反码、补码都一样
  3. 负数的反码 = 其原码符号位不变,其余位置取反
  4. 负数的补码 = 其反码 + 1,负数的反码 = 其补码 - 1
  5. 0 的反码、补码都是 0
  6. java 中的数都是有符号的
  7. 计算机在运算时,都是以补码的方式来运算的 ( 统一了符号的正负 )
  8. 但当查看运算结果的时候,是原码方式展示

位运算符

  • 按位与:&( 两位全为 1,结果才为 1 )
    • 例:2 & 3
      • 2 原码 ( 00000000 00000000 00000000 00000010 ) 转补码,正数不变
      • 3 原码 ( 00000000 00000000 00000000 00000011 ) 转补码,正数不变
      • & 运算:00000000 00000000 00000000 00000010 转原码不变:得 2
    • ——> 2
  • 按位或:| ( 两位中有一位 1,则为 1 )
  • 按位异或:^( 两位中一个 1,一个 0 时,结果才为 1 )
  • 按位取反:~ ( 0 —> 1,1 —> 0 )
    • 例1:~ - 2
      • 先得 - 2 的原码 ( 10000000 00000000 00000000 00000010 )
      • 想要得补码,得先转反码 ( 11111111 11111111 11111111 11111101 )
      • 补码 = 反码 + 1:11111111 11111111 11111111 11111110
      • 补码 ~ 取反:00000000 00000000 00000000 00000001
      • 则运算后的补码转原码:00000000 00000000 00000000 00000001
    • ——> 1
    • 例2:~ 2
      • 2 的原码,正数等于补码:00000000 00000000 00000000 00000010
      • ~ 2 运算:11111111 11111111 11111111 11111101( 负 )
      • 运算后补码转原码:负数要补转反,再反转原
      • 反码 = 补码 - 1:11111111 11111111 11111111 11111100
      • 原码 = 反码 ( 符号不变 ) :10000000 00000000 00000000 00000011
    • ——> - 3
  • 算术右移:>>( 低位溢出,符号位不变,并用符号位补溢出的高位 )
    • 例:int a = 1 >> 2( 右移两位 )
      • 1:00000000 00000000 00000000 00000001
      • 右移两位:00000000 00000000 00000000 00000000 ( 01 )
      • 本质是 1 / 2 / 2
    • ——> 0
  • 算术左移:<<( 符号位不变,低位补 0 )
    • 例:int b = 1 << 2( 左移两位 )
      • 1:...... 00000001
      • 左移两位:...... 00000100
      • 本质是 1 * 2 * 2
    • ——> 4
  • 逻辑右移 ( 无符号右移 ):>>> ( 低位溢出,高位补 0 )

三大流程控制语句

  1. 顺序控制
  2. 分支控制
  3. 循环控制

顺序控制

程序从上到下逐行执行,中间没有任何判断和跳转

分支控制

  • 单分支 if

    • if(条件表达式){
          执行代码块;
      }
      
    • 条件表达式为 true,执行代码块,false 则跳过执行代码块

  • 双分支

    • if(条件表达式){
          执行代码块1; 
      }else{
          执行代码块2; 
      }
      
    • 条件表达式为 true,执行代码块1,否则执行代码块2

// 判断一个年份是否为闰年
Scanner scanner = new Scanner(System.in);
int year = scanner.nextInt();
if((year % 4 == 0 && year % 100 != 0) || year % 400 == 0){...}
  • 多分支

    • if(条件表达式){
          执行代码块1; 
      }else if{
          执行代码块2; 
      }else{
          执行代码块;
      }
      
    • 多分支也可以没有else,此时如果都不成立,则无执行入口

    • 异常处理机制( 之后涉及 )

  • 嵌套分支,if 里面加各种 if 分支( 多了可读性会变差 )

  • switch 分支

    • switch(表达式){
          case 常量1:
              语句块1 
              break; 
          case 常量2:
              ... 
              break; 
          default: 
              ... 
              break; 
      }
      
    • 结构上

      • break 表示直接退出 switch
      • 如果 case1 执行完且没有break,则不用判断直接执行下一个 case2 的语句块,以此类推直到 break,没有就执行到结尾完成switch
      • 可穿透,例:case 1: case 2: case 3: ... break; // 1、2、3 同一种显示
      • 如果一个 case 都没能匹配上就执行 default
    • 使用要求

      • 表达式数据类型应和 case 后的常量一致,或者能自动转换成可比较的类型( 比如输入字符 char,常量可以是 int )
      • switch 里的表达式的返回值必须是:byte、short、int、char、String、enum ( 枚举 ),例如小数的话就会报错,必要情况下只能自行强转先
      • case 的必须是常量 / 常量表达式,不能是变量
      • 语句中也可以没有 default

循环控制

  • for 循环控制

    • for(循环变量初始化; 循环条件; 循环变量迭代){ 
          循环操作(可以多条语句); 
      }
      
    • 循环变量初始化 —> 循环条件 T —> 循环操作 —> 循环变量迭代 —> 循环条件 T ...... 循环条件 F —> for循环结束

    • 循环条件是返回布尔值的表达式

    • for( ; 循环判断条件 ; ) 中的初始化和变量迭代可以省略写外面

      // 在循环过后还想使用原本的i,就把i写外面
      int i = 1;
      // i写for里面就只能用在循环里面
      for( ; i <= 10; ){
          i++;
      //  ....
      }
      
      for(;;){ }  // 表示一个无限循环,死循环
      
    • 循环初始值可以有多条初始化语句,但要求类型一样,而且中间用逗号隔开

​ 循环条件只有一条

​ 循环变量迭代也可以有多条变量迭代语句,中间用逗号隔开

  • while 循环控制

    • while(循环条件){ 
          循环体(语句);
          循环变量迭代;
      }
      
  • do...while 循环控制

    • do{
          循环体(语句);
          循环变量迭代;
      }while(循环条件);
      
    • 先执行再判断,不管什么情况都至少执行一次

    • 与 while 相比,最后是有一个分号的

多重循环控制

  • 各种循环控制语句嵌套,只有内层循环 false 后,才结束外层的当次循环

  • 化繁为简 —> 逐步搭建 —> 变量替代定数 ( 代码优化,便于修改 )

  • 经典打印金字塔

    for(int i = 1; i <= 5; i++){			 //         *
        for(int j = 1; j < 5 - i; j++){		 //	   ***
            System.out.print(" ");		 //	  *****
        }						 //	 *******
        for(int z = 1; z <= 2 * i - 1; z++){       //	*********
            System.out.println("*");		 
            // print 加上 ln 就自动换行 
        }
    }
    // 空心金字塔
    int tol = 5;
    for(int i = 1; i <= tol; i++){			 		 
        for(int j = 1; j < tol - i; j++){				 
            if(j == 1 || j == 2 * i - 1 || j == tol){ //      * 
                System.out.print("*");		    //	   * *	 
            }else{		          	    //	  *   *
                System.out.print(" ");		    //	 *     *
            }		   			    //	*********