Python语言程序设计之程序设计基本方法
Posted
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Python语言程序设计之程序设计基本方法相关的知识,希望对你有一定的参考价值。
参考技术A计算机的概念:计算机是 根据指令操作数据的设备 。
计算机具有 功能性 和 可编程性。
功能性,指对数据的操作,表现为数据计算、输入输出处理和结果存储等。
可编程性,指根据一系列指令自动地、可预测地、准确地完成操作者的意图。
计算机的发展参照 摩尔定律 ,表现为指数方式。
计算机硬件所依赖的集成电路规模参照摩尔定律发展,计算机运行速度因此也接近几何级数快速增长,计算机高效支撑的各类运算功能不断丰富发展。
摩尔定律 Moore’s Law——计算机发展 历史 上最重要的预测法则
Intel公司创始人之一戈登·摩尔在1965年提出单位面积集成电路上可容纳晶体管的数量约每两年翻一番,CPU/GPU、内存、硬盘、电子产品价格等都遵循摩尔定律。计算机是当今世界,唯一长达50年有效且按照指数发展的技术领域,计算机深刻改变人类 社会 ,甚至可能改变人类本身,可预见的未来30年,摩尔定律还将持续有效。
程序设计
程序设计是计算机可编程性的体现。
程序设计,亦称编程,是深度应用计算机的主要手段,程序设计已经成为当今 社会 需求量最大的职业技能之一,很多岗位都将被计算机程序接管,程序设计将是生存技能。
程序设计语言
程序设计语言是一种用于交互(交流)的人造语言。
程序设计语言,亦称编程语言,是程序设计的具体实现方式,编程语言相比自然语言更简单、更严谨、更精确,编程语言相比自然语言更简单、更严谨、更精确。
编程语言种类很多,但生命力强劲的却不多。编程语言有超过600种,绝大部分都不再被使用。C语言诞生于1972年,它是第一个被广泛使用的编程语言,Python语言诞生于1990年,它是最流行最好用的编程语言。
编程语言的执行方式
计算机执行源程序的两种方式:编译和解释。
源代码:采用某种编程语言编写的计算机程序,人类可读。
例如:result = 2 + 3
目标代码:计算机可直接执行,人类不可读 (专家除外)。
例如:11010010 00111011
编译
将源代码一次性转换成目标代码的过程。
执行编译过程的程序叫作编译器(compiler)。
解释
将源代码逐条转换成目标代码同时逐条运行的过程
执行解释过程的程序叫做解释器(interpreter)。
编译和解释
编译:一次性翻译,之后不再需要源代码(类似英文翻译)。
解释:每次程序运行时随翻译随执行(类似实时的同声传译)。
静态语言和脚本语言
根据执行方式不同,编程语言分为两类。
静态语言:使用编译执行的编程语言,如C/C++语言、Java语言。
脚本语言:使用解释执行的编程语言,如Python语言、JavaScript语言、PHP语言。
执行方式不同,优势也各有不同。
静态语言:编译器一次性生成目标代码,优化更充分,程序运行速度更快。
脚本语言:执行程序时需要源代码,维护更灵活,源代码在维护灵活、跨多个操作系统平台。
IPO
程序的基本编写方法。
I:Input 输入,程序的输入。
P:Process 处理,是程序的主要逻辑。
O:Output 输出,程序的输出。
理解IPO
输入 ,程序的输入 文件输入、网络输入、控制台输入、交互界面输入、内部参数输入等,输入是一个程序的开始。
输出 ,程序的输出,控制台输出、图形输出、文件输出、网络输出、操作系统内部变量输出等,输出是程序展示运算结果的方式。
处理 ,处理是程序对输入数据进行计算产生输出结果的过程,处理方法统称为 算法 ,它是程序最重要的部分,算法是一个程序的灵魂。
问题的计算部分
一个待解决的问题中,可以用程序辅助完成的部分。
计算机只能解决计算问题,即问题的计算部分,一个问题可能有多种角度理解,产生不同的计算部分,问题的计算部分一般都有输入、处理和输出过程。
编程解决问题的步骤
6个步骤 (1-6)
分析问题 :分析问题的计算部分,想清楚。
划分边界 :划分问题的功能边界,规划IPO。
编写程序 :编写问题的计算机程序,编程序。
调试测试 :调试程序是正确运行的,运行调试。
升级维护 :适应问题的升级维护,更新完善。
求解计算问题的精简步骤
3个精简步骤
确定IPO :明确计算部分及功能边界。
编写程序 :将计算求解的设计变成现实。
调试程序 :确保程序按照正确逻辑能够正确运行。
编程能够训练思维
编程体现了一种抽象交互关系、自动化执行的思维模式。计算思维:区别逻辑思维和实证思维的第三种思维模式。能够促进人类思考,增进观察力和深化对交互关系的理解。
编程能够增进认识
编程不单纯是求解计算问题。不仅要思考解决方法,还要思考用户体验、执行效率等方面。能够帮助程序员加深对用户行为以及 社会 和文化的认识。
编程能够带来乐趣
编程能够提供展示自身思想和能力的舞台。让世界增加新的颜色、让自己变得更酷、提升心理满足感。在信息空间里思考创新、将创新变为现实。
编程能够提高效率
能够更好地利用计算机解决问题。显著提高工作、生活和学习效率。为个人理想实现提供一种借助计算机的高效手段。
编程带来就业机会
程序员是信息时代最重要的工作岗位之一。国内外对程序员岗位的缺口都在百万以上规模。计算机已经渗透于各个行业, 就业前景非常广阔。
学习编程的误区
Q:编程很难学吗? A:掌握方法就很容易!
首先,掌握编程语言的语法,熟悉基本概念和逻辑。其次,结合计算问题思考程序结构,会使用编程套路。最后,参照案例多练习多实践,学会举一反三次。
Java语言核心技术之基本程序设计
Java语言核心技术之基本程序设计
2.1 标识符和关键字
标识符是在程序开发时给包,类、接口、注解,变量,方法命名的字符序列。
标识符在命名时需要遵守相关的命名规则和命名规范:
标识符的命名规则:
- 标识符不能是Java的关键字和保留字,关键字是Java中被赋予赋予特殊含义的单词,例如public static void等等。保留字是现有Java版本尚未使用,但是未来的Java版本可能会做关键字使用的单词,例如goto,const。但是可以包含关键字,保留字。
- 标识符可以由字母、数字、下划线组成,但是不能以数字开头
日常开发中应该严格遵守标识符的命名规则,否则程序会出现编译错误。
在IntelliJ IDEA中,Java的关键字都是橙黄色
如果你想了解Java语言有多少关键字,可以访问Oracle官网获取
https://docs.oracle.com/javase/tutorial/java/nutsandbolts/_keywords.html
标识符的命名规范:
- 包名统一使用小写,点分隔符之间有且仅有一个自然语义的英语单词。包名统一使 用单数形式,但是类名如果有复数含义,类名可以使用复数形式。,例如com.taobao
- 类名单词首字母大写,多个单词首字母也要大写,例如HelloWorld
- 变量名、方法名首字母小写,后面单词首字母大写,例如myName,testVarriable()
- 常量名单词字母全部大写,多个单词使用下划线隔开,例如ORDER_TYPE
- 虽然Java支持Unicode字符集,但是标识符不能是中文,同时禁止使用中英文混合命名,更不允许直接使用中文的命名方式,建议命名时见名知意。
由于软件开发是团队协作,标识符的命名规范不遵守不会出现错误,但是遵守标识符的命名规范可以提高程序的可读性,便于后期维护,因此日常开发中也应该严格遵守。
package net.ittimeline.java.core.foundational.syntax;
/**
* Java标识符
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:21
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class IdentifierTest {
public static void main(String[] args) {
CustomerInfo customerInfo = new CustomerInfo();
customerInfo.setCustomerName("tony");
System.out.println("customerInfo name is " + customerInfo.getCustomerName());
System.out.println("customerInfo id card id " + CustomerInfo.CUSTOMER_ID_CARD);
}
}
/**
* 类的命名
*/
class CustomerInfo {
/**
* 成员变量的命名
*/
private String customerName;
/**
* 常量的命名
*/
public static final String CUSTOMER_ID_CARD = "430904458902219877";
/**
* 方法的命名
*
* @return
*/
public String getCustomerName() {
return this.customerName;
}
public void setCustomerName(String customerName) {
this.customerName = customerName;
}
}
同学们可以参考JDK提供的API文档,这里以java.lang.String为例子,借鉴官方的命名方式,包括包名(java.lang)、类名(String),属性名(value),方法名(concat),常量名(CASE_INSENSITIVE_ORDER )
2.2 变量
2.2.1 变量的概述
变量代表内存的某个存储区域,该区域的数据可以在同一类型之内随着业务逻辑不断发生变化,例如银行的利率,游戏中人物的位置等等。
变量作为最基本的存储数据的单元,由变量名、变量类型和变量值组成。通过操作变量,就可以方便的操作内存中的数据。
2.2.2 变量的定义和使用
Java是强类型的语言,变量在定义时必须要明确变量的数据类型。变量定义的语法格式为 数据类型 变量名=变量值;
,数据类型可以是Java的基本数据类型和引用数据类型两种。 变量名必须遵守标识符的命名规则和规范,=表示赋值,即将"="右边的值赋值给左边的变量,Java中的相等性使用"=="表示,变量的值可以是对应变量数据类型取值范围内的值。例如 int age=28
;
变量的定义也可以是先声明,再进行赋值
//先声明一个整数变量
int number;
//将整数变量number赋值为10
number=10;
变量定义后,Java会根据变量的数据类型在内存中开辟对应的空间存储数据。
变量在使用前必须声明并赋初始值,如果使用了未声明的变量,程序会发生编译错误,如果使用了未赋值的变量,程序会发生运行时错误。
package net.ittimeline.java.core.foundational.syntax.variable;
/**
* Java变量的使用
* 变量的声明格式
* <p>
* 变量类型 变量名=变量值;
* 变量必须初始化赋值后才能使用
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:22
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class VariableTest {
public static void main(String[] args) {
//变量的声明赋值
int age = 28;
System.out.println("current age = " + age);
//修改变量的值
//同一时刻,变量只有一个值,新值会覆盖旧值
age = 29;
System.out.println("next year age = " + age);
//如果使用了未声明的变量,会发生编译错误
//编译时找不到变量name的声明
// System.out.println("my name is "+name);
String name;
//局部变量声明之后还要初始化赋值才能使用
//System.out.println("my name is "+name);
}
}
在使用变量时,只能在定义时的作用域内使用。在同一个作用域下不能定义重复的变量名。
package net.ittimeline.java.core.foundational.syntax.variable;
/**
* 变量的作用域
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:23
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class VariableScopeTest {
public static void main(String[] args) {
//这里会发生编译错误,因为整数变量age在test方法中定义,只能在test方法中使用
// System.out.println(" my age is "+age);
}
/**
* 自定义test方法用于演示变量的作用域
*/
public static void test() {
int age = 28;
//这里会发生编译错误,在同一个作用域下,不能定义重复的变量
// int age = 29;
}
}
2.2.4 变量的分类
变量按照其作用域可以分为局部变量、成员变量以及类变量。
在方法中声明的变量叫做局部变量,作用域和生命周期从属于方法。
package net.ittimeline.java.core.foundational.syntax.variable.scope;
/**
* 局部变量的使用
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:23
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class LocalVariableTest {
public static void main(String[] args) {
{
int age = 29;
}
//这里无法使用代码块中的age变量,因为age只能在当前{}作用域内访问
//System.out.println("age = "+age);
int score = 100;
System.out.println("score = " + score);
}
}
成员变量是在方法外部、类中定义,并未使用static修饰的变量,成员变量的作用域和生命周期从属于对象,
访问成员变量时需要实例化对象,然后通过对象.成员变量名访问。
package net.ittimeline.java.core.foundational.syntax.variable.scope;
/**
* 成员变量的使用
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:24
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class MemberVariableTest {
/**
* 方法外部,类中声明两个成员变量
*/
String name;
int age;
public static void main(String[] args) {
//实例化MemberVariableTest对象
MemberVariableTest memberVariableTest = new MemberVariableTest();
//通过对象的引用memberVariableTest.name访问成员变量
memberVariableTest.name = "tony";
memberVariableTest.age = 29;
System.out.println("name is " + memberVariableTest.name + " age is " + memberVariableTest.age);
}
}
成员变量和类变量由Java负责初始化,初始化的值是由变量的类型决定的,例如int类型的变量初始化为0,boolean类型的变量初始化为false。而局部变量由程序员手动初始化。
package net.ittimeline.java.core.foundational.syntax.variable.scope;
/**
* Java成员变量的初始化机制
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:25
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class MemberVariableDefaultInitialization {
char c;
int i;
MemberVariableDefaultInitialization() {
System.out.println(" i = " + i);
System.out.println(" c = [" + c + ‘]‘);
}
public static void main(String[] args) {
MemberVariableDefaultInitialization memberVariableDefaultInitialization = new MemberVariableDefaultInitialization();
}
}
类变量是在方法外部、类中定义,使用static修饰的变量,作用域和生命周期从属于类。访问类变量通过类名.成员变量名。
package net.ittimeline.java.core.foundational.syntax.variable.scope;
/**
* 静态变量的使用
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:24
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class StaticVariableTest {
public static void main(String[] args) {
System.out.println(User.ID_CARD);
//静态变量可以直接由类名.变量名访问
System.out.println(User.remark);
}
}
class User {
static final String ID_CARD = "421023199302888588";
/**
* 静态变量由Java负责初始化
*/
static String remark;
}
2.2.5 变量的交换
在Java中,变量的交换有三种方式实现,分别是使用中间变量、算术运算以及异或运算三种方式实现。
package net.ittimeline.java.core.foundational.syntax.variable;
/**
* 变量交换
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:25
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class VariableSwapTest {
public static void main(String[] args) {
int left = 5;
int right = 10;
//通过引入中间变量tmp实现变量的交换
System.out.println("通过引入中间变量tmp实现变量的交换");
System.out.println("交换变量之前");
println(left, right);
// tmp=5 left=5
int tmp = left;
//left=10,right=10
left = right;
right = tmp;
System.out.println("交换变量之后");
println(left, right);
//通过算术运算+ -实现交换
System.out.println("通过算术运算实现交换");
left = 5;
right = 10;
System.out.println("交换变量之前");
println(left, right);
//left=15 right=10
left = left + right;
//right=5 left=15
right = left - right;
//left=10 right=5
left = left - right;
System.out.println("交换变量之后");
println(left, right);
//通过异或运算实现变量交换
System.out.println("通过异或运算实现变量交换");
left = 5;
right = 10;
System.out.println("交换之前");
println(left, right);
left = left ^ right;
right = left ^ right;
left = left ^ right;
System.out.println("交换之后");
println(left, right);
}
/**
* 输出left和变量的值
*
* @param left
* @param right
*/
public static void println(int left, int right) {
System.out.println("left = " + left + " right = " + right);
}
}
2.3 数据类型
在计算机底层数据都是使用二进制表示的,使用起来不太方便,因此引入数据类型的概念,数据类型用于对不同的数据进行分类,其原因在于
- 不同的类型所能存储的数据类型不同,
- 不同表示的数据范围(极限)也不同
- 不同的数据类型 在内存中占据的空间(字节数量)也不同
- 不同的数据类型参与不同的运算。
Java的数据类型分为基本数据类型(Primitive Type)和引用数据类型(Reference Type)两大类,如下列表所示,目前只讨论基本数据类型
其中基本数据类型都有数组类型,数组就是一片连续的存储空间。
而基本数据类型不具有面向对象的编程机制,也没有对象的特性:没有成员变量、方法可以被调用,因此Java八种基本数据类型对应的引用类型,也被称为包装类。
基本数据类型 | byte | short | int | long | float | double | boolean | char |
---|---|---|---|---|---|---|---|---|
包装类 | Byte | Short | Integer | Long | Float | Double | Boolean | Character |
2.4 整型
2.4.1 Java整型的极限
整型是日常生活中常用的类型,例如人的年龄,大楼的层数等等。
Java中的整型按照占据不同内存大小,可以分为byte,short,int,long四种类型。
其中整数默认是int类型,long类型的变量值需要加L后缀。
可以通过查看其包装类Byte的源码获取其表示数据的范围
以及Byte占据的位数和字节数
其他类型可以使用同样的方式通过查看包装类的源码获取存储数据的表示范围以及占据的字节带小。
使用四种整数类型的包装类获取其对应的数据存储范围以及占据的字节数量。
package net.ittimeline.java.core.foundational.syntax.datatype;
/**
* 整数的极限以及内存大小
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:29
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class IntegerLimitsTest {
public static void main(String[] args) {
//这里的%d表示整数占位符,会被对应的数值替换
System.out.printf("byte所能存储的最大值是%d,所能存储的最小值是%d,占据的字节数量是%d
",Byte.MAX_VALUE,Byte.MIN_VALUE,Byte.BYTES);
System.out.printf("short所能存储的最大值是%d,所能存储的最小值是%d,占据的字节数量是%d
",Short.MAX_VALUE,Short.MIN_VALUE,Short.BYTES);
System.out.printf("int所能存储的最大值是%d,所能存储的最小值是%d,占据的字节数量是%d
",Integer.MAX_VALUE,Integer.MIN_VALUE,Integer.BYTES);
System.out.printf("long所能存储的最大值是%d,所能存储的最小值是%d,占据的字节数量是%d
",Long.MAX_VALUE,Long.MIN_VALUE,Long.BYTES);
}
}
在使用对应的数据类型时,需要注意不要超过其存储的极限(即最大值和最小值),否则程序会发生错误。
2.5.2 大整数BigInteger
日常开发中使用的整数是byte,int,long以及对应的包装类,整数默认是int,而long类型的常量值后面需要添加L后缀,如果想要使用比Long更大范围的数据,可以使用java.math包中的BigInteger类。
package net.ittimeline.java.core.foundational.syntax.datatype;
import java.math.BigInteger;
/**
* Java大整数
* Java整型有byte short int long 四种类型,常用的有byte,int和long
* 整数默认是int
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:30
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class BigIntegerTest {
public static void main(String[] args) {
byte bt=-128;
System.out.println("bt = "+bt);
//
int INT_MAX_VALUE=Integer.MAX_VALUE;
System.out.println("int max value is "+INT_MAX_VALUE);
//long类型的变量值如果超过了int的表示范围,需要使用L后缀
//全球人口数量
long totalPopulation=76_0000_0000L;
System.out.println("totalPopulation = "+totalPopulation);
//如果想要表示宇宙的星球数量,假如是1万亿亿 long类型也不能够存储
//long starQuantity=1_0000_0000_0000_0000_0000L;
//此时可以使用JDK提供的BigInteger来存储大整数
String starQuantityStr="100000000000000000000";
//使用BigInteger的String构造器创建BigInteger对象
BigInteger starQuantity=new BigInteger(starQuantityStr);
System.out.println("starQuantity = "+starQuantity);
}
}
2.5.3 整数的四种进制类型
在Java中,整数支持四种进制类型,分别是二进制、八进制、十进制和十六进制。其中JDK1.7以后支持二进制,以0b开头,而八进制是以0开头,十六进制是以0x开头
package net.ittimeline.java.core.foundational.syntax.datatype;
/**
* 整数的四种进制类型
* 在Java中,整数支持四种进制类型,分别是二进制、八进制、十进制和十六进制。
* 其中JDK1.7以后支持二进制,以0b开头,而八进制是以0开头,十六进制是以0x开头
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:31
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class IntegerRadix {
public static void main(String[] args) {
byte binary=0b1100;
System.out.println("二进制变量binary = "+binary);
short oct=012;
System.out.println("八进制进制变量oct = "+oct);
int value=12;
System.out.println("十进制变量value = "+value);
long hex=0x12;
System.out.println("十六进制变量hex = "+hex);
}
}
在日常企业开发中基本使用的都是十进制的整数,但是在JDK源码以及其他场景中中会使用到其他进制,
Integer类就使用了十六进制的常量来表示int的取值范围。
2.5.4 数值字面量使用下划线
如果Java源文件中存在着很长的数字字面量(即变量值),不易阅读,此时可以使用JDK7以后新增的特性:数值字面量使用下划线来分割数值,使其更加容易阅读。
我们可以在整数和浮点数的数值之间使用下划线,编译器在编译时会删除这些下划线。
package net.ittimeline.java.core.foundational.syntax.datatype;
/**
* 数值字面量使用下划线
* 如果Java源文件中存在着很长的数字字面量(即变量值),不易阅读,此时可以使用JDK7以后新增的特性:数值字面量使用下划线来分割数值,使其更加容易阅读。
* 我们可以在整数和浮点数的数值之间使用下划线,编译器在编译时会删除这些下划线。
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/18 19:32
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class IntegerFloatUnderScoreTest {
public static void main(String[] args) {
//很长的变量值,不容易阅读
long number=12000000000000L;
//数值使用下划线分割,更加容易阅读,编译器在编译时会删除下划线
System.out.println("number = "+ number);
number=12_0000_0000_0000L;
//因此在输出number变量的值时不会看到下划线
System.out.println("number = "+ number);
double value=3.1415_926;
System.out.println("value = "+value);
}
}
2.6 浮点型
2.6.1 浮点型的两种表示方式
浮点数就是生活中常用的小数,例如银行的利率,股市的涨跌等等都是浮点数。
Java中的浮点数类型分为单精度浮点型float和双精度浮点型double两种,默认是double类型,如果想要使用float类型,变量值后面加上f后缀,浮点数可以使用十进制和科学计数法两种表示方式。
package net.ittimeline.java.core.foundational.syntax.datatype;
/**
* Java基本数据类型-浮点型
*数学意义上的小数就是浮点型
* float和double是Java的两种浮点类型
* 浮点数默认是double,如果想使用float,变量值后面跟f后缀
* 浮点数在进行运算时存在着误差
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/19 11:07
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class FloatTest {
public static void main(String[] args) {
//float类型的变量值后面要加上f后缀,否则会出现编译错误
float flt = 12.0f;
//浮点类型默认是double
double dbl = 12.0;
//使用科学计数法表示浮点数
double value = 1.2e1;
System.out.println("flt = " + flt);
System.out.println("dbl = " + dbl);
System.out.println("value = " + value);
double source = 3.1415926;
//3.1415926 等价于 31415926e-7
double target = 31415926e-7;
System.out.println("source =" + source);
System.out.println("target =" + target);
}
}
2.6.2 浮点型的极限以及存储方式
float占据四个字节(Byte),也就是32位(bit),double占据八个字节(Byte),也就是64位,而由于浮点数的存储机制和整数的不一样,Java的浮点数准守IEEE754标准,采用二进制的科学计数法表示浮点数。
对于float,第一位是符号位,接下来八位表示指数,接下来23位表示尾数。
对于double,第一位是符号位,接下来11尾数表示指数,接下来52表示尾数。
float所能表示的最大值会比占据8个字节的long都要大。
package net.ittimeline.java.core.foundational.syntax.datatype;
/**
* 浮点型的极限以及存储方式
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/19 11:08
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class FloatLimitsTest {
public static void main(String[] args) {
//这里的%e表示整数占位符,会被对应的科学计数法替换
System.out.printf("float所能存储的最大值是%e,所能存储的最小值是%e,占据的字节数量是%d
",Float.MAX_VALUE,Float.MIN_VALUE,Float.BYTES);
//使用科学计数法表示float最大值
float floatMaxExponent=3.402823e+38f;
//使用十进制小数表示float最大值
Float floatMax=340282300000000000000000000000000000000f;
System.out.println("floatMaxExponent = "+floatMaxExponent);
System.out.println("floatMax = "+floatMax);
//由于浮点数的存储机制不同占据四个字节的float表示的数据极限比占据八个字节的Long还要大
System.out.printf("long所能存储的最大值是%d,所能存储的最小值是%d,占据的字节数量是%d
",Long.MAX_VALUE,Long.MAX_VALUE,Long.BYTES);
System.out.printf("double所能存储的最大值是%e,所能存储的最小值是%e,占据的字节数量是%d
",Double.MAX_VALUE,Double.MIN_VALUE,Double.BYTES);
}
}
2.6.3 浮点数精度问题
单精度的float有效位数是7位,即小数点后能保留7位,第八位会进行四舍五入处理。
双精度的double有效位数是16位,即小数点后保留16位,第十七位会进行四舍五入处理。
如果在使用float或者double的小数时,超过了有效位数进行相关的运算时会得到错误的结果。
package net.ittimeline.java.core.foundational.syntax.datatype;
/**
* 浮点数精度问题
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/19 11:09
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class FloatPrecisionTest {
public static void main(String[] args) {
float floatValue=1.123_456_789f;
//输出结果是1.1234568 1.123456789,小数点后截取7位,第8位会进行四舍五入
System.out.println("floatValue = "+floatValue);
double doubleValue=1.111_222_333_444_555_666_777;
//输出结果是1.1112223334445557 1.111222333444555666777,小数点后截取16位,第17位会进行四舍五入
System.out.println("doubleValue = "+doubleValue);
//浮点类型的数据在运算时运算结果会有误差
float floatSource=2.0f;
//float类型的浮点数小数有效位数是7位
float floatTarget=1.2_222_222f;
//0.7777778
float floatResult=floatSource-floatTarget;
System.out.println("float source = "+floatSource);
System.out.println("float target = "+floatTarget);
//运算结果为 0.7777778 因为float的有效位数是7位
System.out.println("float result = "+floatResult);
//double类型的 2.0-1.1获取的计算结果是错误的
double doubleSource=2.0;
double doubleTarget=1.1;
double doubleResult=doubleSource-doubleTarget;
System.out.println("double source = "+doubleSource);
System.out.println("double target = "+doubleTarget);
//运算结果为 0.8_999_999_999_999_999 因为double的有效位数是16位
System.out.println("double result = "+doubleResult);
//如果数据超过了有效位数,在进行相关运算时(例如这里的关系运算:相等)也会得到错误的结果
double source=1.000_000_000_000_000_001;
double target =1.000_000_000_000_000_002;
System.out.println("source == target ? "+(source==target));
}
}
如果想要获取更高的精度,例如金融计算的业务场景中,会使用到更高精度,此时可以使用java.math包中的BigDecimal来完成。
package net.ittimeline.java.core.foundational.syntax.datatype;
import java.math.BigDecimal;
/**
* 无损精度计算
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/19 11:09
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class BigDecimalTest {
public static void main(String[] args) {
//使用字符串构建BigDecimal对象
BigDecimal sourceBigDecimal = new BigDecimal("2.0");
BigDecimal targetTargetDecimal = new BigDecimal("1.1");
//调用BigDecimal提供的subtract方法实现减法运算 解决了浮点数double计算的精度问题
BigDecimal resultBigDecimal = sourceBigDecimal.subtract(targetTargetDecimal);
System.out.println("resultBigDecimal = " + resultBigDecimal);
double source=1.000_000_000_000_000_001;
double target =1.000_000_000_000_000_002;
BigDecimal doubleSourceBigDecimal=new BigDecimal(source);
BigDecimal doubleTargetBigDecimal=new BigDecimal(target);
/**
* 使用BigDecimal对象提供的equals方法判断是否相等 这里的结果是true
* 在使用BigDecimal时不能使用double构造BigDecimal对象,否则会得到错误的结果
*/
System.out.println("doubleSource equals doubleTarget ? "+doubleSourceBigDecimal.equals(doubleTargetBigDecimal));
//将上面的数字转换为字符串之后就能获取精确的运算结果
String sourceStr="1.000000000000000001";
String targetStr="1.000000000000000002";
//只能使用String构造BigDecimal才能获取精确的运算结果
BigDecimal strSourceBigDecimal=new BigDecimal(sourceStr);
BigDecimal strTargetBigDecimal=new BigDecimal(targetStr);
System.out.println("strSource equals strTarget ? "+strSourceBigDecimal.equals(strTargetBigDecimal));
}
}
2.7 布尔型
布尔类型只有boolean一个类型,而且其取值只能是true或则false。在日常开中boolean常常和关系、逻辑运算以及条件判断语句一起使用。
package net.ittimeline.java.core.foundational.syntax.datatype;
/**
* Java基本数据类型-boolean类型
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/19 11:10
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class BooleanTest {
public static void main(String[] args) {
//产生2个0-1之间的随机小数
double source=Math.random();
double target=Math.random();
System.out.println("source = "+source);
System.out.println("target = "+target);
// >就是关系运算
boolean result=source>target;
System.out.println("result = "+result);
//这里等价于result==true
if(result){
System.out.println("source > target");
}else{
System.out.println("source < target");
}
}
}
2.8 字符型
Java中的字符使用char表示,用于存储单个字符,字符型的变量值使用‘‘包含。
由于Java使用16位的Unicode作为编码方式,而Unicode是国际组织制定的可以容纳世界上所有文字和符号的字符编码方案,因此Java程序支持各种语言的字符。
除此以外char还能使用Unicode表示字符,由于其占据2个字节空间大小,其表示范围是u0000 - uFFFF。在日常开发中还会使用到一些常用的转义字符,例如实现换行的 以及实现路径转义的等等。
字符在计算机底层都是以数字的方式存储的,例如字符‘a‘底层的数字是97,‘A‘底层的数字是65,字符‘0‘的底层数字是48,然后依次递增。
package net.ittimeline.java.core.foundational.syntax.datatype;
/**
* Java基本数据类型-字符型
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/19 11:11
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class CharacterTest {
public static void main(String[] args) {
//Java支持Unicode标准,可以存储世界上所有国家的语言文字
//英文
char english=‘L‘;
//中文
char chinese=‘刘‘;
//日文
char japan=‘お‘;
//韩文
char korean=‘?‘;
System.out.println("english = "+english);
System.out.println("chinese = "+chinese);
System.out.println("japan = "+japan);
System.out.println("korean = "+korean);
char A=‘u0041‘;
//大写字母A对应的数字是65
System.out.println("unicode \\u0041 对应的字符是 = "+A);
char a=‘u0061‘;
//小写的字母a对应的数字是97
System.out.println("unicode \\u0061对应的字符是 = "+a);
//字符0对应的数字是48
char zero=‘u0030‘;
System.out.println("unicode \\u002F对应的字符是"+zero);
char newLine=‘
‘;
System.out.print("hello"+newLine+"world");
char path=‘\\‘;
System.out.println("path = "+path);
}
}
2.9 数据类型转换
2.9.1 数据类型自动转换
Java中的八种基本数据类型除了boolean之外,在进行算术运算时,会按照如下的规则进行自动类型转换。
byte,short,char->int->long->float->double
当byte,short,char三种类型的变量运算时结果类型为int
- byte和byte运算的结果类型是int
- byte和short运算的结果类型是int
- byte和char运算的结果类型是int
- char和char运算的结果类型是int
- char和short运算的结果类型是int
- int和int运算的结果类型是int
- byte,short,int,long和float运算结果类型是float
- byte,short,int,long,float和double运算结果类型是double
即表示范围小的变量会自动提升为表示范围大的变量,这里的表示范围指的是数据类型对应的取值范围,而不是数据类型占用的内存空间,例如float取值范围要大于long的取值范围。
自动类型转换可以在一定程度上避免进行运算的时候结果超过数据类型的极限而造成程序错误。
package net.ittimeline.java.core.foundational.syntax.datatype.convert;
/**
* 自动类型转换
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/19 11:13
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class AutoTypeConvert {
public static void main(String[] args) {
//byte和int运算的结果是int
byte byteVal=12;
int intVal=12;
//如果用byte存储运算结果,会编译失败
int intResult=byteVal+intVal;
System.out.println("intResult = "+intResult);
float floatResult=byteVal+intVal;
System.out.println("floatResult = "+floatResult);
//容量小的变量值自动转换为容量大的变量
short shortVal=12;
double dblValue=shortVal;
char ch=‘a‘;
int intNewValue=123;
int intNewResult=ch+intNewValue;
System.out.println("intNewResult = "+intNewResult);
byte sourceByte=12;
char targetChar=12;
int resultInt=sourceByte+targetChar;
//short和char运算结果类型是int
short shortNewVal=29;
char newChar=‘b‘;
int result=shortNewVal+newChar;
// byte和byte运算也是int
byte source=12;
byte target=12;
int sourceTarget=source+target;
System.out.println("sourceTarget = "+sourceTarget);
//int
int maxTarget=Integer.MAX_VALUE;
int maxSource=Integer.MAX_VALUE;
//这里已经超出了int表示的最大值,因此输出的结果是错误的
int maxResult=maxSource+maxTarget;
System.out.println("maxResult = "+maxResult);
}
}
2.9.2 数据类型强制转换
而在某些应用场景下我们还可能会使用到强制类型转换,例如数据库查询返回的结果是long类型,但是需要强制转换为int类型。
强制类型转换是自动类型转换的逆运算,使用强转符()实现,如果强转的变量超过目标类型的最大值会损失精度。
package net.ittimeline.java.core.foundational.syntax.datatype.convert;
/**
* 数据类型强制转换
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/19 11:16
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class NarrowTypeConvert {
public static void main(String[] args) {
double dblVal=12.8;
System.out.println("dblVal = "+dblVal);
//强制类型转换 (强转类型)
int intVal=(int)dblVal;
//强制转换可能会损失精度
System.out.println("intVal = "+intVal);
//如果转换的变量值(例如这里的12)在强制转换类型的表示范围之内(例如这里的byte)则不会损失精度
long longVal=12;
byte byteVal=(byte)longVal;
System.out.println("longVal = "+longVal+ " byteVal = "+byteVal);
int sourceVal=128;
byte targetVal=(byte)sourceVal;
//这里会损失精度,因为128已经超过了byte存储的最大值
System.out.println("sourceVal = "+sourceVal+ " targetVal = "+targetVal);
}
}
在给变量赋值时,如果变量的值没有超过变量类型的极限,赋值时也会发送自动类型转换,但是如果赋值时变量的值超过了变量类型的极限,那么此时就需要使用到强制类型转换实现。
package net.ittimeline.java.core.foundational.syntax.datatype.convert;
/**
* 赋值运算特性
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/19 11:17
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class AssignmentFeature {
public static void main(String[] args) {
//整型常量默认为int,浮点常量默认为double
//虽然long类型的变量值必须加上L后缀,但是这里的123就是int,这里实际上就是发生了自动类型转换
long longSourceVal=123;
System.out.println("int max"+Integer.MAX_VALUE);
// 因为2147483648超过了int表示的最大值,所以这里必须加上L后缀
long bigSource=2147483648L;
System.out.println(" bigLongSource = "+bigSource);
//3.14默认是double类型,在赋值是必须使用强制类型转换
//因为将表示范围大的值赋值给表示范围小的变量必须强制类型转换
float fltVal= (float) 3.14;
//整型默认的是int类型
byte byteVal=12;
int result=byteVal+1;
//浮点型默认是double
double dblVal=12.3+byteVal;
System.out.println("dblVal = "+dblVal);
}
}
2.10 String
2.10.1 字符串变量
日常开发中最常用的数据类型是String,它用于存储字符串,使用" "包含起来,String位于java.lang包下,属于引用类型的一种,底层是字符数组。
String类型变量的定义以及与char类型的比较
package net.ittimeline.java.core.foundational.syntax.datatype;
/**
* 字符串变量
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/19 11:19
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class StringTest {
public static void main(String[] args) {
//String类型的变量定义 变量值使用""包含
String str = "Hello World";
String charConent = "c";
System.out.println("charContent = " + charConent);
//空字符
char emptyC = ‘ ‘;
System.out.println("emptyC= [" + emptyC + "]");
//空字符串
String emptyStr = " ";
System.out.println("emptyStr= [" + emptyStr + "]");
}
}
2.10.2 字符串连接
String可以和八种基本数据类型使用加号(+)做连接运算,运算的结果类型是String。
String类型与基本数据类型的连接运算,如果加号前后有String类型的变量,那么此时的加号就是表示连接,如果+前后没有String,此时的加号表示算术运算的加法。
package net.ittimeline.java.core.foundational.syntax;
/**
* 字符串与八种基本数据类型的运算
* 字符串可以和八种基本数据类型进行连接运算,使用+表示连接,运算的结果类型是String类型
* +符号前后有String表示连接,没有String表示算术运算的加法
*
* @author liuguanglei ittimelinedotnet@gmail.com
* @version 2019/11/19 11:20
* @wechat 18601767221
* @website ittimeline.net
* @since JDK11
*/
public class StringOperatorTest {
public static void main(String[] args) {
String info="";
int age=18;
String name="刘光磊";
double height=176.0;
boolean isMarry=false;
long id=362352355643454356L;
info="id : "+id+"姓名:"+name+"
年龄:"+age+"
身高:"+height+"
是否已婚"+isMarry;
System.out.println("******个人信息******");
System.out.println(info);
//判断+表示字符串连接还是算术运算的加法
char charVal=‘a‘;
int number=10;
String str="hello";
//第一个加法前后都不是String,因此表示加法,而不是字符串连接,而a表示97,第二个加法后面是String,因此表示字符串连接
//最后的运算结果是107hello
System.out.println(charVal+number+str);
//第一个加法后面是String,运算结果是ahello10
System.out.println(charVal+str+number);
//第一个加法后面是String,运算结果是ahello10
System.out.println(charVal+(str+number));
//第一个加法前后都不是String,因此加号表示算术运算符的加法运算,最后的运算结果是107hello
System.out.println((charVal+number)+str);
String star="*";
char tab=‘ ‘;
String content=star+tab+star;
System.out.println("content ="+content);
}
}
2.11 数据在内存中的存储方式
数据在内存中有三种表现方式:原码、反码和补码
数据在内存中都是以二进制的补码存储,在理解补码之前首先得理解原码以及反码。
- 原码
原码就是一个数据本身的二进制表现形式,而数值可以分为有符号和无符号两种。
有符号数其二进制表示最高位(最左边)是符号位,1表示负数,0表示正数。
例如无符号数15的原码使用一个字节表示为0000 1111
例如有符号15的原码使用一个字节表示为0000 1111
例如有符号-15的原码使用一个字节表示为1000 1111
- 反码
无符号数的反码等于原码
例如无符号数15的反码等于原码,即无符号数15的反码用一个字节表示为0000 1111
有符号数正数的反码也等于原码
例如有符号正数15的反码等于原码,即有符号数15的反码用一个字节表示为0000 1111
有符号负数的反码是原码最高位不变,其他位取反
例如有符号负数-15的反码是原码最高位不变,其他位取反用一个字节表示为1111 0000
- 补码
无符号数的补码等于反码
例如无符号数15的补码等于反码,即无符号数15的补码使用一个字节表示为0000 1111
有符号正数的补码等于反码
例如有符号正数15的补码等于反码,即有符号正数15的补码使用一个字节表示为0000 1111
有符号负数的补码等于反码加1
例如有符号负数-15的补码等于反码1111 0000加1,即有符号负数15的补码使用一个字节表示为11111 0001
数值 | 是否有符号 | 原码 | 反码 | 补码 |
---|---|---|---|---|
15 | 否 | 0000 1111 | 0000 1111 | 0000 1111 |
15 | 是 | 0000 1111 | 0000 1111 | 0000 1111 |
-15 | 是 | 1000 1111 | 1111 0000 | 1111 0001 |
无符号数以及有符号正数,计算机存储的是原码,因为原码等于反码
有符号负数计算机存储的是补码,补码等于原码取反加1,原码等于补码取反加1。
以上是关于Python语言程序设计之程序设计基本方法的主要内容,如果未能解决你的问题,请参考以下文章