精华内容
下载资源
问答
  • 输入一个二进制数,将其转换为十进制数。 题目解析 这道题,就是一个进制转换的问题。从二进制第一位数开始求十进制数,如图所示: 代码样例 package com.asong.leetcode.BinarytoDecimal; import java.util....

    前言:
    这道题就是一个简单的进制转换,在网上看到了这道题,所以就写一下,在此记录一下。

    题目描述

    输入一个二进制数,将其转换为十进制数。

    题目解析

    这道题,就是一个进制转换的问题。从二进制第一位数开始求十进制数,如图所示:
    在这里插入图片描述

    代码样例

    package com.asong.leetcode.BinarytoDecimal;
    
    import java.util.Scanner;
    
    /**
     * 二进制转10进制
     */
    public class Solution {
        public int BinaryToDecimal(int[] array)
        {
            if(array==null && array.length==0)
            {
                return 0;
            }
            int result = 0;
            int index = array.length-1;
            for (int i = index; i >=0; i--) {
                if(array[i]>=0 && array[i]<=1)
                {
                    if(array[i] == 1) {
                        result = result + (int) Math.pow(2.0,index-i);
                    }
                }else {
                    return 0;
                }
            }
            return result;
        }
    
        public static void main(String[] args) {
            Scanner scanner = new Scanner(System.in);
            Solution solution = new Solution();
            while(scanner.hasNext())
            {
                String string = scanner.nextLine();
                String[] str = string.split(",");
                int[] array = new int[str.length];
                for (int i = 0; i < str.length; i++) {
                    array[i] = Integer.parseInt(str[i]);
                }
                int result =solution.BinaryToDecimal(array);
                System.out.println(result);
            }
        }
    }
    
    
    展开全文
  • 最近有点忙,现在稍微闲一些,就想写写最近遇到的一些业务。...这里附上雪花算法工具类以及六十进制工具类: public class SnowflakeUtil { // ==============================Fields==============.

    最近有点忙,现在稍微闲一些,就想写写最近遇到的一些业务。

    业务:一些商户、市场、档口等主体需要有唯一编码。
    思路:一些前缀+雪花算法,此时位数过多,再转成六十四进制缩短位数即可。同时为了实现批量生成唯一,可在生成唯一码的时候加上synchronized static关键字,实现类对象锁。

    这里附上雪花算法工具类以及转成六十四进制工具类:

    
    public class SnowflakeUtil {
    	// ==============================Fields===========================================
    	/** 开始时间截 (2020-08-25 00:00:00) */
    	private final static long twepoch = 1598284800000L;
    
    	/** 机器id所占的位数 */
    	private final static long workerIdBits = 5L;
    
    	/** 数据标识id所占的位数 */
    	private final static long datacenterIdBits = 5L;
    
    	/** 支持的最大机器id,结果是31 (这个移位算法可以很快的计算出几位二进制数所能表示的最大十进制数) */
    	private final long maxWorkerId = -1L ^ (-1L << workerIdBits);
    
    	/** 支持的最大数据标识id,结果是31 */
    	private final long maxDatacenterId = -1L ^ (-1L << datacenterIdBits);
    
    	/** 序列在id中占的位数 */
    	private final static long sequenceBits = 12L;
    
    	/** 机器ID向左移12位 */
    	private final static long workerIdShift = sequenceBits;
    
    	/** 数据标识id向左移17位(12+5) */
    	private final static long datacenterIdShift = sequenceBits + workerIdBits;
    
    	/** 时间截向左移22位(5+5+12) */
    	private final static long timestampLeftShift = sequenceBits + workerIdBits + datacenterIdBits;
    
    	/** 生成序列的掩码,这里为4095 (0b111111111111=0xfff=4095) */
    	private final static long sequenceMask = -1L ^ (-1L << sequenceBits);
    
    	/** 工作机器ID(0~31) */
    	private static long workerId = 0;
    
    	/** 数据中心ID(0~31) */
    	private static long datacenterId = 0;
    
    	/** 毫秒内序列(0~4095) */
    	private static long sequence = 0L;
    
    	/** 上次生成ID的时间截 */
    	private static long lastTimestamp = -1L;
    
    	// ==============================Constructors=====================================
    	/**
    	 * 构造函数
    	 * 
    	 * @param workerId     工作ID (0~31)
    	 * @param datacenterId 数据中心ID (0~31)
    	 */
    	public SnowflakeUtil() {
    		if (workerId > maxWorkerId || workerId < 0) {
    			throw new IllegalArgumentException(
    					String.format("worker Id can't be greater than %d or less than 0", maxWorkerId));
    		}
    		if (datacenterId > maxDatacenterId || datacenterId < 0) {
    			throw new IllegalArgumentException(
    					String.format("datacenter Id can't be greater than %d or less than 0", maxDatacenterId));
    		}
    //		this.workerId = workerId;
    //		this.datacenterId = datacenterId;
    	}
    
    	// ==============================Methods==========================================
    	/**
    	 * 获得下一个ID (该方法是线程安全的)
    	 * 
    	 * @return SnowflakeId
    	 */
    	public synchronized static long nextId() {
    		long timestamp = timeGen();
    
    		// 如果当前时间小于上一次ID生成的时间戳,说明系统时钟回退过这个时候应当抛出异常
    		if (timestamp < lastTimestamp) {
    			throw new RuntimeException(String.format(
    					"Clock moved backwards.  Refusing to generate id for %d milliseconds", lastTimestamp - timestamp));
    		}
    
    		// 如果是同一时间生成的,则进行毫秒内序列
    		if (lastTimestamp == timestamp) {
    			sequence = (sequence + 1) & sequenceMask;
    			// 毫秒内序列溢出
    			if (sequence == 0) {
    				// 阻塞到下一个毫秒,获得新的时间戳
    				timestamp = tilNextMillis(lastTimestamp);
    			}
    		}
    		// 时间戳改变,毫秒内序列重置
    		else {
    			sequence = 0L;
    		}
    
    		// 上次生成ID的时间截
    		lastTimestamp = timestamp;
    
    		// 移位并通过或运算拼到一起组成64位的ID
    		return ((timestamp - twepoch) << timestampLeftShift) //
    				| (datacenterId << datacenterIdShift) //
    				| (workerId << workerIdShift) //
    				| sequence;
    	}
    
    	/**
    	 * 阻塞到下一个毫秒,直到获得新的时间戳
    	 * 
    	 * @param lastTimestamp 上次生成ID的时间截
    	 * @return 当前时间戳
    	 */
    	protected static long tilNextMillis(long lastTimestamp) {
    		long timestamp = timeGen();
    		while (timestamp <= lastTimestamp) {
    			timestamp = timeGen();
    		}
    		return timestamp;
    	}
    
    	/**
    	 * 返回以毫秒为单位的当前时间
    	 * 
    	 * @return 当前时间(毫秒)
    	 */
    	protected static long timeGen() {
    		return System.currentTimeMillis();
    	}
    
    	// ==============================Test=============================================
    	/** 测试 */
    	public static void main(String[] args) {
    		for (int i = 0; i < 400; i++) {
    			long id = SnowflakeUtil.nextId();
    			System.out.println(id);
    		}
    	}
    }
    
    
    
    import java.math.BigDecimal;
    import java.math.BigInteger;
    
    /**
     * 64进制转换
     *
     * @author liujingyu
     *
     *         2020年8月26日 liujingyu@caseeder.com
     */
    
    public class ConvertNumUtil {
    
    	private static String S64BASE = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ@#";
    
    	public static String to64String(BigInteger i) {
    		BigDecimal divide = new BigDecimal(64);
    		BigDecimal decimal = new BigDecimal(i);
    		String res = "";
    		// 循环取余
    		while (BigDecimal.ZERO.compareTo(decimal) != 0) {
    			BigDecimal[] divRes = decimal.divideAndRemainder(divide);// 返回数组:[0] 商值(this / val) , [1] 余数(this % val)
    			decimal = divRes[0];
    			res = S64BASE.charAt(divRes[1].intValue()) + res;
    		}
    		return res;
    	}
    
    }
    
    

    参考文章:
    浅析Java中synchronized与static synchronized
    转:雪花算法的原理和实现Java

    展开全文
  • 1、软考考试情况说明 b站视频 1.1、考试形式: 上午:计算机与软件工程知识:150分钟,笔试,...2.1.2、十进制转R进制 2.1.3、二进制转八进制与十六进制 二进制转八进制 将二进制从右到左拆分,每三位为一个集体,到最

    1、软考考试情况说明

    b站视频

    1.1、考试形式:

    上午:计算机与软件工程知识:150分钟,笔试,选择题
    下午:软件设计:150分钟,笔试,问答题(第一道数据流图,第二道数据库,第三道UML,第四道数据结构与算法,第五第六二选一:C++,java,以设计模式为背景来考试这一块)

    1.2、历年考试情况:

    在这里插入图片描述
    在这里插入图片描述

    2、计算机组成与体系结构

    2.1、数据的表示

    2.1.1、R进制转十进制

    在这里插入图片描述

    2.1.2、十进制转R进制

    在这里插入图片描述

    2.1.3、二进制转八进制与十六进制

    二进制转八进制
    将二进制从右到左拆分,每三位为一个集体,到最左边不够三位的时候可以补0凑够三位,然后将每一个三位转为8进制。
    二进制转十六进制
    将二进制从右到左拆分,每四位为一个集体,到最左边不够四位的时候可以补0凑够四位,然后将每一个四位转为16进制。
    在这里插入图片描述

    2.1.4、原码、反码、补码、移码

    在这里插入图片描述
    移码作为浮点运算中的阶码

    • 正数的原码是8位二进制数,最高位代表符号位,正数符号位是0
    • 正数的反码跟原码一样
    • 正数的补码跟原码一样
    • 正数的移码是在补码的基础上将符号位取反

    • 负数的原码8位二进制数,最高位代表符号位,负数的符号位是1
    • 负数的反码是原码的符号位不变,其它位与原码相反
    • 负数的补码是在反码的基础上加一
    • 负数的移码是在补码的基础上将符号位取反

    2.1.5、数据的表示范围

    在这里插入图片描述
    补码比原码和反码都多了一个范围,这是因为0的差异,-0的原码和反码跟+0的原码和反码是不一样的,但是-0和+0的补码是一样,都是00000000;
    注意:-0的反码为1111 1111 变为补码后是在反码的基础上加1,所以变为0000 0000;最多以为进位溢出了存到一个寄存器中,不用管丢弃了。

    2.1.6、浮点数运算

    在这里插入图片描述
    对阶的时候需要小阶向大阶看齐,所以这里的1.19*10^2 要换算为 3的次方。然后尾数进行相加。
    结果格式化的时候如果是0.1要换成1.0,要是11.0要换成1.10;

    2.2、计算机结构

    在这里插入图片描述

    2.3、计算机体系结构分类-Flynn

    在这里插入图片描述

    2.4、CISC和RISC

    考试形式:是比较CISC和RISC的区别
    在这里插入图片描述
    可变长格式:在计算机中有二进制编码,编码的长度可以不同,称为可变长
    定长格式:编码长度都是一样的,称为定长。
    操作寄存器(使用他的原因):寄存器速度极快,效率极高
    硬布线逻辑控制为主的原因:效率高,硬件的复杂度高,但是一旦设计出来效率就比软件高。

    2.5、流水线

    流水线主要考计算问题

    2.5.1、流水线的基本概念

    在这里插入图片描述
    未使用流水线:大量的时间片处于空闲状态
    使用流水线:充分利用空闲的时间片

    2.5.2、流水线的计算(考的多)

    计算流水线的执行时长问题
    流水线周期:一条指令开始到下一条指令最晚开始时间的总称。

    • 理论公式:同一时间第二条指令在分析,要2ns,所以这里第一条执行完了要等这2ns结束之后才可以进行下一条指令执行,因此计算的时候,将流水线分为两个部分,第一部分是第一条指令完成取指、分析和执行的时间,第二部分是后面指令执行的时间,后面指令执行的时候都是在第一部分的基础上根据流水线周期进行的,所以时间就是*流水线周期。
    • 实践公式:k是代表从哪里切开有多少条指令,这里的第一部分是有3条指令,那么这里的k就是3。
    • 总结:考试中先选择理论公式计算,要是题目中没有对应答案,就选择实践公式计算。
      在这里插入图片描述
      在这里插入图片描述

    2.5.3、流水线的吞吐率计算

    在这里插入图片描述

    2.5.4、流水线的加速比计算

    以上面的流水线例子来说明,不使用流水线的时候执行时间为:(2+2+1)100;使用流水线执行时间2+2+1+992=203;
    在这里插入图片描述

    2.5.5、流水线的效率的计算

    在这里插入图片描述

    2.6、存储系统

    速度上面快,容量下面的大
    cpu可以与直接调用内存,引入Cache是为了提高访问速度。
    cpu要读取东西的时候,先从Cache中读取,如果cache中没有,cpu会到内存中去调用。访问命中率就是我读取cache的时候能够获取到我需要的东西的概率
    在这里插入图片描述

    2.6.1、Cache

    • 使用Cache可以提高速度的直观计算:Cache+主存储器的系统平均周期计算。
    • 访问命中率就是我读取cache的时候能够获取到我需要的东西的概率
      在这里插入图片描述

    2.6.2、局部性原理

    速度高的,成本高,成本低的,速度又慢,局部性原理解决问题

    • 时间局部性:比如S+=j,在一开始的时候加载在cache中,下次访问就直接从cache中访问,这样就不用每次都到内存中获取。
    • 空间局部性:例如数组,程序访问第一个空间是0的时候,要是继续访问第二个空间的0的时候。
    • 工作集理论:频繁访问的存入cache。
      在这里插入图片描述

    2.6.3、主存–分类

    • 随机存取存储器:一断电数据就丢失。
    • 只读存储器:断电数据不会丢失
      在这里插入图片描述

    2.6.4、主存–编址

    在这里插入图片描述
    在这里插入图片描述
    在这里插入图片描述

    2.6.5、磁盘结构与参数

    • 磁盘的基本运作原理:多碟的磁盘,有多张盘在里面,每一个盘面存储一定的信息,磁头升到盘面,完了之后要读取信息的话,磁头先要挪到相应的磁道上面,这需要消耗一定时间,这个时间称为寻道时间。第二个是旋转延时时间,也称为等待时间,一个磁道上面分为很多扇区,一个磁道的一小块就是扇区,存储数据的时候就是存储在一个一个扇区里。假设磁头没有在读取信息对应的扇区,那么要旋转磁盘,使得磁头对应在读取数据相对应的扇区,所以会有一个等待时间。
    • 磁道:在一个环里面,一圈一圈的同心圆就是磁道,存信息的时候是存在磁道上面
      在这里插入图片描述
    • 物理块:扇区
    • 缓存区:是将磁盘中的信息读取出来暂存的地区
    • 单缓存区:只有一个缓存区,当读取第二个数据的时候,应为只有一个缓存区,那么第一个数据还没处理完,第二个数据是不可以进入缓存区读取的,又因为磁盘是不断转动的,所以到达第二个数据的时候数据进不了缓存区,而是直接转到了第三个数据,所以等到第一个数据处理完毕,那么磁盘已经转动到R2的位置了可能,但是我们想处理完R0之后处理R1,所以磁盘会继续往前转动,转回到R1的时候R1的记录就进入缓存区处理数据。
    • 优化:就是在处理完R0之后就遇到R1,处理完R1就到达R2;相当于转了两圈将所有数据处理完,3112=66;

    在这里插入图片描述
    在这里插入图片描述
    相当于转了两圈将所有数据处理完,3112=66;
    在这里插入图片描述

    2.7、总线系统

    • 内部总线:微机内部各个外围芯片与处理器之间的总线,是芯片的一个级别的。
    • 系统总线:微机中各个插件版和系统版之间的总线,是属于插件版的一个级别的。比如PCI接口,VGI的接口。
    • 外部总线:微机和外部设备的总线。
      在这里插入图片描述

    2.8、可靠性

    2.8.1、系统可靠性分析–串联系统与并联系统

    • 串联:只要一个过程出错就会不能正常运行
    • 并联:只有所有过程都出现问题的时候才会不能正常运行
    • 串联可靠性计算:各个过程的可靠性相乘。
    • 串联失效率计算:各个过程的失效率累加起来,这个只是个近似的计算,可能没那么准确。比如20个串联起来,每个过程的可靠性为0.9,那么每个过程的失效率为0.1;所以计算出来失效率为2.0,那么就是200%是失效的,逻辑上是错误的,所以计算失效率个公式只是个近似公式,在子系统比较多,而且每个失效率极低的情况下,可以使用这个公式快速计算。
    • 并联可靠性计算:计算所有系统同时失效的概率,然后将各个失效的概率相乘,然后再用1将去这个失效率,那么就是可靠性。
    • 并联失效率计算:1-可靠性就得出了失效率。
      在这里插入图片描述

    2.8.2、系统可靠性分析–模冗余系统与混合系统

    将错误的Rm结果去掉,少数服从多数,所以最后输出结果是对的。
    这个不常考了。
    在这里插入图片描述
    常考题型

    在这里插入图片描述

    2.9、校验码

    2.9.1、差错控制–CRC与海明校验码

    • 检错:检查出错误
    • 纠错:不但要检查出错误,还要纠正错误
    • 通过增大码距来解决纠错问题

    在这里插入图片描述

    2.9.2、循环校验码CRC(检错但不能纠错)

    • 普通除法计算:直接上面减下面
    • 模2除法:是按位做异或操作,异或的意思是不同取1,相同取0
      在这里插入图片描述
    • CRC检错原理:原始报文在进行信息编码的时候,在他的尾部加入一些校验信息(在尾部加入生成多项式的位数减1个0。),加入这些校验信息之后与生成的多项式相除,得到的余数加在原始报文后面得到的就是编码后的数据,让编码后的数据能够与循环校验码的生成多项式做模2相除余数为0,接收方如果校验的时候发现除后余数不为0则表示传输过程中出现问题。
      在这里插入图片描述

    2.9.3、海明校验码(难点常考)

    • 规定好了校验码的位置,所以除了校验码的位置,其余空的位置才可以放信息位,比如你要处理一位的信息位,那么最后的编码长度应该为3,因为第一位要放校验码,第二位也要放校验码,所以信息位只能放在第三的位置。如果要放置的信息位有5位,那么编码长度就为9,因为第五的信息要放置在第九位的位置,第八位要放校验位。
    • 4是信息的位数
    • r是校验码的位数

    在这里插入图片描述

    • 计算校验位的时候,看信息位所在的位置然后用二进制表示这个位置,二进制表示这些信息位的位置的时候,有对应的校验位的都做异或操作,得到的结果就是校验位的数据。
    • 传输过程中出错,收到信息之后,再把这个信息求出校验位,得到的校验位跟之前的校验位做异或操作,得出的结果可以看出是哪个位置出现错误。比如异或之后的结果为001,那么就是第一个位置出错,如果是010,就是第二个位置出错,如果是110那么就是第六个位置出错了。

    在这里插入图片描述

    3、操作系统原理

    3.1、操作系统概述

    操作系统用于管理整个系统的软硬件资源,如果说将计算机买回来之后,没有装操作系统,就不能去控制计算机的资源,所以操作系统是人和硬件之间的一种接口,比如点击鼠标,读取数据,或者存储数据,都需要依赖于操作系统。操作系统也是硬件与软件之间的接口,接口往往是命令,比如以前的操作系统,都是用命令来操控计算机,windows系统可以直观的操控系统,命令的方式,窗口的方式,都属于人和计算机之间的接口,而应用软件和硬件之间的接口,指的是api的接口,就是应用软件要调用硬件资源的时候,可以通过操作系统装配应用软件提供的api接口来实现相关的功能。

    在这里插入图片描述
    在这里插入图片描述

    3.2、进程管理

    3.2.1、进程状态转换图

    在这里插入图片描述

    3.2.2、进程管理–前驱图

    前驱图表示完成一系列活动的前后的约束关系
    在这里插入图片描述

    3.2.3、进程管理–进程的同步与互斥

    同步与互斥是不是反义词?不是
    同步–异步
    互斥–共享
    在这里插入图片描述

    • 无论是单缓冲区还是多缓冲区都存在同步与互斥问题;
    • 单缓冲区的同步问题:生产者要放东西的时候,如果市场中有东西,那么生产者不可以放,需要停下来等消费者拿走之后才可以放;
    • 单缓冲区的互斥问题:同一时刻只允许一个人操作,不允许生产者与消费者同时操作市场中的东西。
    • 多缓冲区的同步问题:生产者要放东西的时候,如果市场中的东西满了,就不能继续往里面放东西了,得等到消费者消费市场里面的东西之后才可以继续往里面放,跟单缓冲区同步问题的区别就是生产者可以往市场中放东西的容量多了而已。
    • 多缓冲区的互斥问题:市场容量不为1,但是生产者和消费者还是不能同一时刻操作市场中的东西。
      在这里插入图片描述

    3.2.4、进程管理–PV操作

    • p操作之后是将信号量减1,当信号量没有小于0的时候就不会被阻塞,会将东西放到缓冲区中去,如果信号量小于0就将进程放到队列中进行等待。
    • v操作之后是将信号量加1,当信号量没有小于等于0的时候就不会被阻塞,会继续从缓冲区拿东西,如果小于等于0就从进程队列中唤醒一个进程。
      在这里插入图片描述
      单缓冲区生产者、消费者问题没有PV操作出现的问题:
    • 一开始生产者生产一个产品,送到缓冲区
    • 生产者继续生产产品,送到缓冲区,这时候出现问题,缓冲区满了,出现溢出问题,所以需要加入pv操作。
    • 如果是消费者开始执行,那么生产者还没有生产东西,缓冲区里是空,消费者执行出现问题。

    单缓冲区生产者、消费者问题PV原语描述:

    生产者进程:

    • s1的初始值为1,s2的初始值为0
    • 首先要生产一个产品,生产者先执行p(s1)操作,执行完之后s1=0;没有小于0就不会被阻塞会继续往下面执行,就会把产品放到缓冲区去
    • 执行v(s2)操作,执行完之后s2=1;这时候不执行消费者进程,而是继续回头执行生产者进程;执行p(s1)操作,这时候s1=-1,小于0所以当前进制就会被放入到进程的等待队列,并将此进程阻塞起来。加入pv操作之后,在第一次生产的产品还没有消费之前,第二次生产的产品会不会被放到缓冲区的。

    消费者进程:

    • 首先执行p(s2)操作,s2=0;没有小于0所以可以继续往下面执行,可以从缓冲区中取东西;
    • 然后执行v(s1)操作,s1=0;s1小于等于0,就会从等待队列中激活一个进程,其实激活的就是生产者。
    • 如果一开始就先从消费者执行,那么执行p(s2)的时候,s2=-1,那么是小于0的,就会被阻塞起来,不能从缓冲区中拿数据。
      在这里插入图片描述

    例子:
    停车场和停车位问题跟这个书店是同一个问题。
    p操作是将信号量减1,v操作是信号量加1,所以比如停车位就可以相当于信号量,如果有车就进入停车场之后,占用一个停车位,那么停车位要减1,这时候就是信号量减1,那么这时候之前的是p操作。车从停车位出来之后,停车位就多出一个空位,那么这时候需要执行的是v操作,信号量加1。

    • 购书者执行p操作,信号量减1,进入购书,要离开的时候执行v操作,信号量加1,离开书店
    • 在进行付款操作的时候,也需要收银员操作,因此存在同步关系。
    • 加入没有pv操作,那么收银员就会不停的进行收费,没有人进行付款的时候收费是没有意义的
    • 所以在收费之前加入p操作,这个p操作需要付款操作来唤醒。因此这个付款需要一个v操作,用来唤醒收银员的p操作。
    • 付款之后不是立马走人,而是得等收银员计算好价格之后,找了零钱之后通知你可以走了才可以走人,所以在付款之后要有一个p操作来阻塞接下来的操作,这个p操作需要收银员收费之后执行v操作来唤醒。
    • 答案选AC

    在这里插入图片描述

    3.2.5、进程管理–PV操作与前驱图的组合问题(常考)

    • A,B,C,D,E都对应一个进程
    • A,B,C一开始没有其他约束,可以随时进行,需要他们唤醒D,所以他们是v操作。
    • D是有约束的,没有ABC就不能向下进行,所以D需要ABC的唤醒,所以是P操作;在搅拌之前要执行p操作,之前完成之后需要一个v操作来唤醒包饺子的E进程。
    • E进程就需要执行p操作
      在这里插入图片描述

    例子:

    • p1和p2需要唤醒p3,所以在p1和p2处需要v操作,p3在执行之前需要p操作,执行之后需要v操作来唤醒p4和p5。
    • 要使用到的信号量,可以使用一种简单的方法放置,从上到下从左到右按照顺序放置信号量,每一个箭头就对应一个信号量。
    • 箭头的起点位置是v操作,箭头的终点位置是p操作。
    • 所以p1位置是v(s1)p2的位置是v(s2);p3开头位置是p(s1),p(s2);p3的结束位置是v(s3),v(s4);p4的开始位置是p(s3),p(s4);这样可以快速解决pv操作问题。
      在这里插入图片描述

    3.2.6、进程管理–死锁问题

    3.2.6.1、死锁的概念

    • 只要需要的资源才不会发生死锁:每个进程所需要的资源减1后的总和加1
    • 比如下面的例子,3个进程都需要5个资源,那么就每个进程分配4个资源,一共需要12个资源,如果再多一个资源就不会发生死锁。所以至少需要13个资源才不会发生死锁。因为每个都有4个资源之后,如果还有一个资源,那么这个资源不管分配给哪个进程,他都会执行下去,然后执行完毕就会释放他本身的资源,这时候其它进程就可以有资源继续进行下去,不至于出现死锁问题。

    在这里插入图片描述

    3.2.6.2、死锁的预防和避免

    在这里插入图片描述

    死锁的四大必要条件:

    • 互斥:如果不是互斥使用资源,大家都可以同时使用那个资源,就不会产生死锁,就因为大家都需要那个资源,但是这个资源同一时间不能被多个进程使用,这时候就会出现死锁。
    • 保持和等待:各个进程会保持自己的资源并等待别人释放更多的资源。
    • 不剥夺:系统不会剥夺其它进程的资源给另一个需要这个资源的进程。
    • 环路等待:A等待B释放资源,B又等待C释放资源,C又在等待A释放资源,就形成了环路等待。

    死锁的预防

    • 打破四大必要条件

    死锁的避免

    • 有序资源分配法
    • 银行家算法

    3.2.6.3、进程管理–银行家算法

    概念
    在这里插入图片描述
    例子
    在这里插入图片描述

    在这里插入图片描述
    在这里插入图片描述

    3.3、存储管理

    3.3.1、存储管理–分区存储组织

    • 作业1和作业2直接的空白区间可能是之前的作业执行完毕释放的空间
    • 首次适应法:按照顺序分配
    • 最佳适应法:采用最小的空白区间分配
    • 最差适应法:采用最大的空白区间分配
    • 循环首次适应法:把空闲的区域连成环形,第一次用25k第二次到28k第三次到10k。分配空间的时候,需要从上次找到空闲分区开始,不是链首开始,所以作业3后面的空闲区域是28k所以会从28k的空闲区域中分割出9k给作业四。
      在这里插入图片描述

    3.3.2、存储管理–页式存储组织

    在这里插入图片描述
    练习题

    • 逻辑地址5A29H转换为物理机制十六进制,从表中找到页号为5的,对应的页帧号为6,那么后面是一样的,物理机制就是6A29H;
    • 要淘汰页号,找到页号为4的对应的状态位为0,要想淘汰页号,则这个页号要在内存中,因此看到页号为0,1,2,5的状态位都为1,说明都在内存中,可以淘汰其中一个,
    • 可以淘汰的条件还有一个就是访问位要为0的时候才可以淘汰,因为访问位为1的,说明被访问过了,被访问过的在短时间内有可能再次被访问,所以只有页号为1的页面的访问位为0,所以淘汰页号为1的页面。
      在这里插入图片描述

    3.3.3、存储管理–段式存储组织

    • 页的大小要一致,段的大小不定

    在这里插入图片描述

    3.3.4、存储管理–段页式存储组织

    在这里插入图片描述

    3.3.5、存储管理–快表

    在这里插入图片描述

    3.3.6、存储管理–页面置换算法

    常考:先进先出、最近最少使用算法
    在这里插入图片描述
    在这里插入图片描述

    3.3.7、练习题

    在这里插入图片描述

    • 第一问:先访问虚拟地址,再访问实际地址,因为划分为6个页面,所以是6*2=12次访问内存。
    • 指令只产生一次缺页中断,操作数产生两次缺页中断,因此题中的swapA,B都是指令,所以只有一次缺页中断,A,B操作数可以有两次,所以一共是5次。

    3.4、文件管理

    3.4.1、文件管理–索引文件结构

    一般结点都是13个

    • 直接索引:直接存储物理盘块;所以内存大小:4k*13=52k

    • 一级间接索引:不再直接存储物理盘块,而是存储物理盘块的地址,最后指向物理盘块;4k4字节=1024;内存大小:4k1024;

    • 二级间接索引:11号节点对应的盘块存地址,地址下一级的盘块还是存储地址,最后指向物理盘块。内存大小:4k10241024;

    • 三次间接索引

    • 10个直接索引,1个一级间接索引,1个二级间接索引,1个三次间接索引
      在这里插入图片描述
      练习题

    • 1k*4字节=256
      在这里插入图片描述

    3.4.2、文件管理–文件和树型目录结构

    在这里插入图片描述

    3.4.3、文件管理–空闲存存储空间的管理

    • 空闲区表法(空闲文件目录):可以用一个表记录空闲的位置
    • 空闲链表法:将空闲的都弄成一个链表,需要使用这些空间的时候再从链表中划分出空闲空间。
    • 位示图法(重点):位示图中1表示已经被占用,0表示空闲,把整个空间分成许多物理块,可以直观的表达出哪些物理块是被占用的,哪些是空闲的。比如电影院买票
    • 成组链接法
      在这里插入图片描述
      练习题
      在这里插入图片描述
      在这里插入图片描述

    3.5、设备管理

    3.5.1、设备管理–数据传输控制方式

    • 程序控制方式:又称为程序查询方式,是低级的,也是cpu介入最多的一种机制,就是整个数据的传输控制可能都要cpu的介入。在这种机制中,外设处于一种被动,他不会主动的去反馈信息,比如传输有没有完成,他不会去说,而是由cpu发出相应的查询指令,查询看有没有传输完,没有传输完就接着继续传输,这个过程就相当于你每次都要问员工,这个工作有没有完成了,所以必然会出现一些问题,因此出现了程序中断方式
    • 程序中断方式:跟程序控制方式很像,但是外设是有主动性的,外设完成相应数据的传输,这时候他就会发送一个中断请求,发出请求,系统就会做出下一步决定,效率相对程序控制方式来说更高了
    • DMA方式:也称为直接控制方式,是有专门DMA控制器,只要是外设和内存直接的数据交换,过程中就有控制器去控制,cpu只要开头的时候做一些记录,做好一些初始化,整个过程都有DMA的控制器控制,完成之后再由cpu接手。
      在这里插入图片描述

    3.5.2、设备管理–虚设备与SPOOLING技术

    在这里插入图片描述

    3.6、微内核操作系统

    • 微内核操作系统:就是把内核做的更小的系统
    • 为什么要做小:可靠性,稳定性,安全性
    • 操作系统作为核心的系统软件,如果操作系统故障,就会影响整个系统运行,如果做小,就会降低这种问题发生概率,将最为核心的部分放入内核中,这样,只有这一小块的出故障才会产生根本性影响,原来放在操作系统内核的部分抽离出去了,作为其他的外接系统,这些系统即使出现故障问题,只要重启这一小块的功能部件的东西,就能解决这个问题。
    • 比如将图形系统放到内核之外,假设图形系统崩溃了,对于微内核没有影响,只要重新启动图形系统就可以了。
    • 微内核操作系统分为核心态和用户态
    • 核心态:就是在微内核中内核这一块运行的情况,出现故障就会严重。
    • 用户态:就是在内核态之外运行的情况,用户态出现故障,没有多大问题。
      在这里插入图片描述

    4、数据库系统

    4.1、三级模式–两级映射(常考)

    • 三级模式–两级映射这种设计属于层次型的架构设计,为我们应用数据库的时候,提供了很多遍历,同时也让整个体系的可维护性和应变能力变的更好一些了。
    • 在系统、计算机上面物理数据库其实就是一个文件。有数据库文件、日志文件等
    • 内模式:内模式是和物理层次的数据库直接关联,内模式管的是我们如何去存储这一系列的数据,数据要存到物理文件中,按什么格式去存储,如何去优化他,这就是内模式需要考虑的问题,关注点在于对数据的存放这一块
    • 概念模式:用数据的时候表的级别,这些表就是对应着概念模式,相当于将数据分成若干张表。这些表根据业务,应用划分,表之间有一定的关联。
    • 外模式:对应的是数据库里面的视图,外模式的应用让我们对这些数据的控制有了更加灵活的处置方式,比如在概念模式中的用户信息的一样表,包含密码,用户名等信息,在运用的时候,要是任何功能模块都可以调用用户的所有信息,那么可能不太安全,而且另外一点如果说概念模式里面的这些表发生了变化,如果应用程序直接去调用这些表,那么这些应用程序也要改变,要是加了外模式之后就不一样了,加了为啊模式之后,我们可以会将原来的数据表进行处理之后形成相应的视图,比如说登录的时候,不需要调用很多信息,主要将用户名,密码调用出来形成视图给登录模块使用,在内部处理的时候,只需要调用用户的基本信息,不需要密码,就建一个视图不包含密码,增加了安全性和灵活性,如果概念模式表这一级发生改变,比如之前是一张表,后面一张改成多张,就可以使用视图将这些表中的一些列组成一些视图。
    • 外模式-概念模式映射:表相应的操作形成视图,表和视图具有一种映射关系,有了这一映射,表发生变化,只需要改映射,不需要改应用程序。
    • 概念模式-内模式映射:内部的存储形式跟表的情况的一种映射关系,意思就是把存储结构进行改变,只需要调整这种映射关系,不需要修改应用程序就能应对这种改变。
      在这里插入图片描述

    4.2、数据库设计过程

    在这里插入图片描述

    4.3、E-R模型

    分析局部的E-R模型之后再整个成整个E-R模型。
    在这里插入图片描述
    在这里插入图片描述

    • 一对一关系:每个实体可以转换成一个关系模式,所以两个实体之间关系是一对一的时候,至少有两个关系模式,还有他们之间的关系也可以单独作为一个关系模式,也可以合到任何一个实体中去,所以至少可转换为2个关系模式
    • 一对多关系:两个实体转换为两个关系模式,还有他们之间的关系可以单独作为一个关系模式,也可以把这个关系合到多的这一边,所以至少可转换为2个关系模式
    • 多对多关系:两个实体转换为两个关系,还有他们之间的关系只能单独作为一个关系模式,所以最少可转换为3个关系模式。
    • 例题中,三个实体分别对应一个关系模式,还有三者之间的关系都是多对多关系,因此他们之间的关系也要单独作为一个关系模式,因此最少可以转换为4个关系模式。
      在这里插入图片描述

    4.4、关系代数

    • 并:两个表中的数据都查询出来,去掉重复的数据。
    • 交:查询两张表中共同部分的数据。
    • 差:s1-s2,就是我有的你没有,s1中有的数据在s2中没有
    • 笛卡尔积:s1*s2,s1中的每条数据对应s2中的所有数据匹配。
    • 投影:只选择需要的列。
    • 选择:选择需要的行。
    • 联接:s1和s2中的列都显示出来
      在这里插入图片描述
      在这里插入图片描述
      在这里插入图片描述

    4.5、规范化理论

    4.5.1、规范化理论–函数依赖

    在这里插入图片描述

    4.5.2、规范化伦理–价值与用途

    • 数据冗余:几条数据都要存D01和计算机系和1号楼这些重复的信息
    • 更新异常:比如修改了第一条数据的计算机系为管理系,那么其他条数据也都要修改,不然就会出现错误。
    • 插入异常:在这下面的图中还体现不出来,下面会讲到
    • 删除异常:
      在这里插入图片描述
    展开全文
  • Java语言程序设计与数据结构(基础篇)第5章 循环 文章目录Java语言程序设计与数据结构(基础篇)第5章 循环一、引言二、while循环三、示例学习:猜...将十进制数转换为十六进制数十二、关键字break和continue(重点

    Java语言程序设计与数据结构(基础篇)第5章 循环笔记

    一、引言

    • 循环是用来控制语句块重复执行的一种构造,Java提供了三种类型的循环语句:while循环、do-while循环和for循环。

    二、while循环

    • 要点提示:while循环在条件为真的情况下,重复地执行语句。
    • 计数器控制地循环:知道循环的次数,使用一个控制变量count来对执行次数计数。
    • 循环继续条件总是放在括号内。只有当循环体只包含一条语句或不包含语句时,循环体的花括号可以去掉。
    • 要保证循环继续条件最终为false,否则while循环将是一个无限循环。
    • 差一错误:循环执行次数多一次或者少一次。

    三、示例学习:猜数字

    要点提示:本示例产生一个随机数,然后让用户反复猜测该数字直到答对为止。

    package com.java;
    
    import java.util.Scanner;
    
    public class GuessNumber {
        public static void main(String[] args) {
            //产生一个随机数
            int number = (int)(Math.random()*100);
            Scanner input = new Scanner(System.in);
            System.out.println("Guess a magic number between 0 and 100");
    
            int guess = -1;
            while(guess != number){
                System.out.println("Enter your guess:");
                guess = input.nextInt();
                if (guess == number){
                    System.out.println("恭喜你猜对了");
                    System.exit(1);
                }else if (guess < number){
                    System.out.println("你猜的小了");
                }else if(guess > number){
                    System.out.println("你猜的大了");
                }
            }
        }
    }
    

    四、循环设计策略

    设计循环的关键是确定需要重复执行的代码,以及循环继续条件。

    第一步:确定需要重复的语句

    第二步:将这些语句放在一个循环中

    第三步:为循环继续条件编码,并为控制循环添加适合的语句。

    五、使用用户确认或者标记值控制循环(有技巧)

    标记位控制的循环:一个循环使用标记值控制它的执行。

    package com.java;
    //读取和计算个数不确定的整数之和
    import java.util.Scanner;
    
    public class SentinelValue {
        public static void main(String[] args) {
            
            Scanner input = new Scanner(System.in);
            System.out.println("请输入一个整数,0代表输入结束:");//如果用do-while这句话不用写
            int number = input.nextInt();
            int sum = 0;
            while (number != 0) {
                sum += number;
                System.out.println("请输入一个整数,0代表输入结束:");
                number = input.nextInt();
            }
            System.out.println("您输入的所有数字的和是:" + sum);
        }
    }
    
    

    注意:不要比较浮点值是否相等来进行循环控制,因为在内存中浮点值是近似的不是准确的。

    六、do-while循环

    要点提示:while循环和do-while循环的不同之处在于计算循环继续条件和执行循环体的先后顺序。

    如果循环中的语句至少需要执行一次,建议使用do-while循环。

    package com.java;
    //do-while至少执行一次
    import java.util.Scanner;
    
    public class TestDoWhile {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            int data;
            int sum = 0;
            do {
                System.out.println("请输入一个数字,0代表输入结束:");
                data = input.nextInt();
                sum += data;
            } while (data != 0);
            System.out.println("您输入的数字之和为:" + sum);
        }
    }
    

    七、for循环

    • for循环使用一个变量来控制循环体的执行次数,以及什么时候循环终止,这个变量称为控制变量。
    • 控制变量必须是在循环结构体之内或之前声明的。如果在循环结构体之内声明,那么在循环结构体之外不能使用控制变量。
    • 如果省略for循环中的循环继续条件,则隐含地认为循环继续条件为true,即无限循环。无限循环最好用while循环书写。

    八、采用哪种循环

    • for循环将控制变量初始化、循环继续条件以及每次迭代之后地调整放在一起,更加简洁,并且相比另外两种循环而言更容易避免出错。
    • 前侧循环:循环继续条件的判断在循环体执行之前进行检测。如for循环和while循环。
    • 后侧循环:循环继续条件的判断在循环体执行之后进行检测。如do-while循环。

    九、嵌套循环

    嵌套循环是由一个外层循环和一个或多个内层循环组成的。

    十、最小化数值错误(有技巧)

    • 在循环继续条件中使用浮点数将导致数值错误。
    • 方法1:将float换位double
    • 方法2:从小到大将数字加到总和值sum上。先加较小数再加较大数是减小误差的一种方法。

    十一、示例学习

    1.求最大公约数(有技巧)

    (1)穷举算法1

    package com.java;
    
    //课本程序清单5-9,利用穷举法求GCD
    
    import java.util.Scanner;
    
    public class GreatestCommonDivisor_1 {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
    
            System.out.println("Enter the first integer: ");
            int n1 = input.nextInt();
    
            System.out.println("Enter the second integer:");
            int n2 = input.nextInt();
    
            int gcd = 1;    //初始化gcd为1
            int k = 2;      //可能的最大公约数
            //从小至大开始枚举
            while (k <= n1 && k <= n2) {
                if (n1 % k == 0 && n2 % k == 0) {
                    gcd = k;
                }
                k++;
            }
            System.out.println("The greatest common divisor for " + n1 + " and " + n2 + " is " + gcd);
    
        }
    }
    
    

    (2)穷举算法2

    package com.java;
    
    //课本课后题5.14求最大公约数
    
    import java.util.Scanner;
    
    public class GreatestCommonDivisor_2 {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.println("Enter the first number: ");
            int firstNumber = input.nextInt();
            System.out.println("Enter the second number: ");
            int secondNumber = input.nextInt();
    
            //求两个数中的最小数,其实不用求,可以直接从firstNumber递减寻找最大公约数
            //若firstNumber是最小数,则它就是我们要用的number
            //若firstNumber不是最小数,那么在secondNumber到firstNumber之间不可能有一个数是它们两个的公约数,if不可能成立,程序不会出错
            //int number = (firstNumber < secondNumber) ? firstNumber : secondNumber;
    
            int gcd = 1;    //初始化最大公约数是1
    
            //从大至小进行遍历
            for (int k = firstNumber; k >= 1; k--) {
                if (firstNumber % k == 0 && secondNumber % k == 0) {
                    gcd = k;
                    break;
                }
            }
    
            System.out.println("The greatest common divisor for " + firstNumber + " and " + secondNumber + " is " + gcd);
        }
    }
    
    

    (3)穷举算法3

    package com.java;
    
    import java.util.Scanner;
    
    //课本程序清单22-3,这个求最大公约数的方法,非常有技巧
    //m和n的最大公约数无非就是四种情况
    //1.m比n大,且n是m的除数,则if (m % n == 0) return n;已经包括此种情况
    //2.m比n大,但是n不是m的除数。因为m和n的gcd一定是两者的除数,所以从任意一个数的一半开始向下寻找即可
    //3.m比n小,但m不是n的除数。因为m和n的gcd一定是两者的除数,所以从任意一个数的一半开始向下寻找即可
    //4.m比n小,且m是n的除数。因为n的除数一定小于等于n的一半,则从n的一半开始向下寻找即可
    //综上,2,3,4可以直接归结为另外以中情况,即m%n!=0,因此有以下代码
    public class GreatestCommonDivisor_3 {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.println("Enter the first number: ");
            int firstNumber = input.nextInt();
            System.out.println("Enter the second number: ");
            int secondNumber = input.nextInt();
            System.out.println("The greatest common divisor for " + firstNumber + " and " + secondNumber + " is " + gcd(firstNumber, secondNumber));
        }
    
        public static int gcd(int m, int n) {
            int gcd = 1;
    
            if (m % n == 0) return n;
    
            for (int k = n / 2; k >= 1; k--) {
                if (m % k == 0 && n % k == 0) {
                    gcd = k;
                    break;
                }
            }
            
            return gcd;
            
        }
    }
    
    

    (4)欧几里得算法

    package com.java;
    
    //程序清单22-4,欧几里得算法求最大公约数
    
    import java.util.Scanner;
    
    public class GCDEuclid {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.println("Enter the first number: ");
            int firstNumber = input.nextInt();
            System.out.println("Enter the second number: ");
            int secondNumber = input.nextInt();
            System.out.println("The greatest common divisor for " + firstNumber + " and " + secondNumber + " is " + gcd(firstNumber, secondNumber));
        }
    
        public static int gcd(int m, int n) {
            if (m % n == 0)
                return n;
            else
                return gcd(n, m % n);
        }
    }
    
    

    2.预测未来学费

    package com.java;
    
    public class FutureTuition {
        public static void main(String[] args) {
            double tuition = 10000;
            int year = 0;
            while (tuition < 20000) {
                tuition *= 1.07;
                year++;
            }
            System.out.println("学费将在" + year + "后翻倍");
        }
    }
    
    

    3.将十进制数转换为十六进制数

    package com.java;
    
    import java.util.Scanner;
    
    public class Dec2Hex {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
    
            System.out.println("请输入一个十进制数:");
            int decimal = input.nextInt();
            //记录十六进制的字符串
            String hex = "";
    
            while (decimal != 0) {
                int hexValue = decimal % 16;
                char hexDigit = (0 <= hexValue && hexValue <= 9) ? (char) (hexValue + '0') : (char) (hexValue - 10 + 'A');
                hex = hexDigit + hex;   //字符串的拼接是有顺序的,不能颠倒顺序。
                decimal /= 16;
            }
            System.out.println("十六进制结果是:" + hex);
        }
    }
    

    十二、关键字break和continue(重点掌握)

    • 要点提示:关键字break和continue在循环中或switch中提供了额外的控制。
    • 关键字continue只是跳出了一次迭代。continue语句总是在一个循环内。对于while循环和do-while循环,continue语句之后会立刻计算循环继续条件。而在for循环中,continue语句之后会立即执行每次迭代后的动作,再计算循环继续条件。
    • 关键字break是跳出了整个循环。

    十三、示例学习:判断回文(有技巧)

    package com.java;
    //判断回文
    import java.util.Scanner;
    
    public class Palindrome {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
    
            System.out.println("请输入一个字符串:");
            String string = input.nextLine();
            int low = 0;
            int high = string.length() - 1;
            boolean isPalindrome = true;
            while (low < high) {
                if (string.charAt(low) != string.charAt(high)) {
                    isPalindrome = false;
                    break;
                }
                low++;
                high--;
            }
            if (isPalindrome) {
                System.out.println(string + "是回文");
            } else {
                System.out.println(string + "不是回文");
            }
    
        }
    }
    
    

    十四、示例学习:显示素数(有技巧)

    1.穷举算法1

    package com.java;
    
    //程序清单5-15,求前50个素数,技巧:n的除数不超过n/2;
    public class PrimeNumber {
        public static void main(String[] args) {
            final int NUMBER_OF_PRIMES = 50;
            final int NUMBER_OF_PRIMES_PER_LINE = 10;
            int count = 0;  //计数器
            int number = 2; //从2开始找素数
            System.out.println("The first 50 prime numbers are \n");
    
            while (count < NUMBER_OF_PRIMES) {
    
                boolean isPrime = true;
    
                for (int divisor = 2; divisor <= number / 2; divisor++) {
                    if (number % divisor == 0) {
                        isPrime = false;
                        break;
                    }
                }
    
                if (isPrime) {
                    count++;
    
                    if (count % NUMBER_OF_PRIMES_PER_LINE == 0) {
                        System.out.printf("%-5d\n", number);
                    } else {
                        System.out.printf("%-5d", number);
                    }
                }
                number++;
            }
        }
    }
    
    

    2.穷举算法2

    package com.java;
    
    //程序清单22-5
    
    import java.util.Scanner;
    
    public class PrimeNumbers {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.print("Find all prime numbers <= n, enter n: ");
            int n = input.nextInt();
    
            final int NUMBER_PER_LINE = 10; //每行输出10个数字
            int count = 0;  //计数器,可控制每行输出
            int number = 2; //从2开始寻找素数
            System.out.println("The prime numbers are: ");
    
            while (number <= n) {
                boolean isPrime = true; //假定number是素数
    
                for (int divisor = 2; divisor <= (int) (Math.sqrt(number)); divisor++) {
                    if (number % divisor == 0) {
                        isPrime = false;
                        break;
                    }
                }
    
                if (isPrime) {
                    count++;
                    if (count % NUMBER_PER_LINE == 0) {
                        System.out.printf("%7d\n", number);
                    } else {
                        System.out.printf("%7d", number);
                    }
                }
                number++;   //检查下一个数字是否是素数
            }
            System.out.println("\n" + count + " prime(s) less than or equal to " + n);
        }
    }
    
    

    3.穷举算法3

    package com.java;
    
    //程序清单22-6,程序清单22-5在for循环的每次迭代都必须计算(int) (Math.sqrt(number)),效率不高
    //如果i不是素数,那必须存在一个素数p,满足i=pq且p≤q。因此如果i不是素数,那么可以找出从2到根号i之间的被i整除的素数。
    //上述命题的逆否命题为:如果不存在一个素数p,满足i=pq,则i是素数
    import java.util.ArrayList;
    import java.util.List;
    import java.util.Scanner;
    
    public class EfficientPrimeNumbers {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.print("Find all prime numbers <= n, enter n: ");
            int n = input.nextInt();
    
            List<Integer> list = new ArrayList<>();
    
            final int NUMBER_PER_LINE = 10;
            int count = 0;
            int number = 2;
            int squareRoot = 1; //检查number是否<=squareRoot
    
            System.out.println("The primes numbers are \n");
    
            while (number <= n) {
                boolean isPrime = true;
    
                if (squareRoot * squareRoot < number) squareRoot++;
    
                for (int k = 0; k < list.size() && list.get(k) <= squareRoot; k++) {
                    if (number % list.get(k) == 0) {
                        isPrime = false;
                        break;
                    }
                }
                
                if (isPrime) {
                    count++;
                    list.add(number);
                    if (count % NUMBER_PER_LINE == 0) {
                        System.out.printf("%-7d\n", number);
                    } else {
                        System.out.printf("%-7d", number);
                    }
                }
                
                number++;
                
            }
            
            System.out.println("\n" + count + " prime(s) less than or equal to " + n);
            
        }
    
    }
    
    

    4.埃拉托色尼筛选法

    package com.java;
    
    //程序清单22-7埃拉托色尼筛选法
    
    import java.util.Scanner;
    
    public class SieveOfEratosthenes {
        public static void main(String[] args) {
            Scanner input = new Scanner(System.in);
            System.out.println("Find all prime numbers <= n, enter n: ");
            int n = input.nextInt();
    
            boolean[] primes = new boolean[n + 1];
    
            for (int i = 0; i < primes.length; i++) {
                primes[i] = true;
            }
    
            //判断从2到根号n中的数是否为素数
            for (int k = 2; k <= n / k; k++) {  //其中k为数字
                if (primes[k]) {//为素数,则将其倍数置为非素数
                    for (int i = k; i <= n / k; i++) {  //其中i为倍数
                        primes[k * i] = false;
                    }
                }
            }
    
            final int NUMBER_PER_LINE = 10;
            int count = 0;
            for (int i = 2; i < primes.length; i++) {
                if (primes[i]) {
                    count++;
                    if (count % NUMBER_PER_LINE == 0) {
                        System.out.printf("%7d\n", i);
                    } else {
                        System.out.printf("%7d", i);
                    }
                }
            }
    
            System.out.println("\n" + count + " prime(s) less than or equal to " + n);
        }
    }
    
    

    十五、关键术语

    • iteration 迭代
    • input redirection 输入重定向
    • loop body 循环体
    • nested loop 嵌套循环
    • off-by-one error 差一错误
    • output redirection 输出重定向
    • pretest loop 前测循环
    • posttest loop 后侧循环
    • sentinel value 标志值

    十六、一些问题

    展开全文
  • 2019-06-09 12:31:57
    题目1:将非负十进制整数n转换成b进制。(其中b=2~16) 1.完成题目1,采用递归思想编程解决问题,要求设计出递归模型(递归出口和递归体的函数式)。 2.程序设计风格良好,实现功能测试代码,确保程序的健壮性。 3....
  • JAVA上百实例源码以及开源项目

    千次下载 热门讨论 2016-01-03 17:37:40
     Java进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系,这些代码面向初级、中级Java程序员。 Java访问权限控制源代码 1个目标文件 摘要:Java源码,...
  • java开源包1

    千次下载 热门讨论 2013-06-28 09:14:34
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • java开源包12

    热门讨论 2013-06-28 10:14:45
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • Java资源包01

    2016-08-31 09:16:25
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • java开源包101

    2016-07-13 10:11:08
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • java开源包11

    热门讨论 2013-06-28 10:10:38
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • java开源包2

    热门讨论 2013-06-28 09:17:39
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • Java进制IO类与文件复制操作实例 16个目标文件 内容索引:Java源码,初学实例,二进制,文件复制 Java进制IO类与文件复制操作实例,好像是一本书的例子,源代码有的是独立运行的,与同目录下的其它代码文件互不联系...
  • java开源包3

    热门讨论 2013-06-28 09:20:52
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • java开源包6

    热门讨论 2013-06-28 09:48:32
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • java开源包5

    热门讨论 2013-06-28 09:38:46
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • java开源包10

    热门讨论 2013-06-28 10:06:40
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • java开源包4

    热门讨论 2013-06-28 09:26:54
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • java开源包8

    热门讨论 2013-06-28 09:55:26
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • java开源包9

    热门讨论 2013-06-28 09:58:55
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • java开源包7

    热门讨论 2013-06-28 09:52:16
    BoneCP很小,只有四几K(运行时需要slf4j和guava的支持,这二者加起来就不小了),而相比之下 C3P0 要百多K。 异步输出框架 AsynWriter 一个Java的类库,用于异步输出记录的简单小框架用于高并发下数据输出使用...
  • Java语言基础下载

    热门讨论 2010-09-07 21:56:38
    第二十六章:JavaScript基础 505 学习目标 505 基本结构 506 JavaScript代码的加入 506 基本数据类型 506 常量 507 表达式和运算符 509 实例 511 JavaScript程序构成 513 事件驱动及事件处理 516 内容总结 519 独立...
  • 操作系统概念第版翻译版

    热门讨论 2013-10-28 11:41:07
    十六章 分布式文件系统 16.1 背景 16.2 命名和透明性 16.2.1 命名结构 16.2.2 命名方案 16.2.3 实现技术 16.3 远程文件访问 16.3.1 基本的缓存设计 16.3.2 缓存位置 16.3.3 缓存更新策略 16.3.4 一致性 16.3.5 ...
  • 4 二进制信号量  7. 5 经典同步问题  7. 5. 1 有限缓冲问题  7. 5. 2 读者一作者问题  7. 5. 3 哲学家进餐问题  7. 6 临界区域  7. 7 管程  7. 8 操作系统同步  7. 8. 1 Solaris 2中的同步  7. 8. 2 ...
  • asp.net知识库

    2015-06-18 08:45:45
    使用.ashx文件处理IHttpHandler实现发送文本及二进制数据的方法 制作一个简单的多页Tab功能 一完美的关于请求的目录不存在而需要url重写的解决方案! 在C#中实现MSN消息框的功能 XmlHttp实现无刷新三联动ListBox 鼠标...
  • BIN:二进制文件 BINHex:苹果的一种编码格式 BMP:Windows或OS/2位图文件 BOOK:Adobe FrameMaker Book文件 BOX:Lotus Notes的邮箱文件 BPL:Borlard Delph 4打包库 BSP:Quake图形文件 BUN:CakeWalk 声音...
  • 、 oracle安装、卸载和启动  硬件要求 物理内存:1GB 可用物理内存:50M 交换空间大小:3.25GB 硬盘空间:10GB  安装 1. 安装程序成功下载,将会得到如下2个文件: 解压文件将得到database文件夹,文件组织...
  • 在新的编程思想中,指针基本上被禁止使用(JAVA中就是这样),至少也是被限制使用。而在我们交换机的程序中大量使用指针,并且有增无减。 2、防止指针/数组操作越界 【案例1.2.1】 在香港项目测试中,发现ISDN话机...

空空如也

空空如也

1 2
收藏数 29
精华内容 11
关键字:

十进制转六进制算法java

java 订阅