Java三种循环结构
第一种: While(条件){循环体}
第二种: for(循环变量的赋值;循环变量循环条件 ;循环变量增加量){循环体}
第三种: do {循环体} while(条件)
退出:break退出循环
第五个: 打印九九乘法表
******优化商品价格猜猜猜******
这里使用的类型是float类型, 价格要产生两位的小数
只能产生整数,Math.round是四舍五入
plan_price=Math.round(Math.random()*1000+1000);
注意:float类型数据注意的地方
(1)float类型在定义赋初值的时候,后面跟上一个f
float plan_price=0.00f;
(2)一般的float类型需要格式化,printf或者String.format
System.out.printf("%.3f",d);
或者String.format(“%.3f”,d)
这里.3f表示小数位数是3位,这里的3可以换成0,换成0就没有小数,默认去掉后面的位数使用四舍五入的方法。
(3)float 由于后台存储精度的问题,一般做加减乘除运算不准确。
double add1=0.1f;
double add2=0.2f;
System.out.println(add1+add2);
System.out.println(add1*add2);
由于精度的原因,后台运算加减乘除是不准确的。
(4)对于精度高的数字,不要轻易做比较运算
public class test_compare {
public static void main(String[] args) {
double compare1=1f;
//小数后的数值超过7位(不包括7),四舍五入的数值与某个值很接近,直接判定相等。
double compare2=0.9999999f;
//如果小数点后8个9,就容易造成精度上的相等。
double compare3=0.99999999f;
System.out.println(compare1==compare2);
System.out.println(compare1==compare3);
}
}
(5)由于精度的问题,注意对float和double的转换,不要做把float类型转成double.
public class test_trans {
public static void main(String[] args) {
float num=1.1f;
double result=(double)num;
System.out.println(result);
}
}
转成double后,如果不对小数点位数做限制,后面由于精度的原因,两个数值不相等.
注意:转化时尽量小数点位数做限制
(6)++运算和—运算也不要放在double类型上
public class test_加加 {
public static void main(String[] args) {
double s1=0.8376029181222121;
for(int i=0;i<10;i++){
System.out.println(s1);
s1++;
}
}
}
运算结果不是简单的加1,后面的数字也有改变,限定小数位数.
总结:对于double或者float类型,不要轻易做转化和运算,做转化和运算前做小数位数的限定.
输入的数据需要匹配用户输入的内容,用户输入不能有字母符号,搜索正则表达式匹配小数
^[0-9]+(.[0-9]{1,2})?$
正则表达式
^表示定义数据形式的开始
$表示定义数据形式的结束
[0-9]表示0-9数字出现任意一个[a-z]a-z任意一个出现即可
后面+号可以有多个,至少1个
后面还可以跟*号,表示可以没有,至少0个
()是可选项
.小数点必须有个点
[0-9]也是0-9任意一个
{1,2}大括号里面的1,2,小数点后面的位数只能1位或者是2位,如果对于数字限定位数,就用大括号
自己练习(简易)
手机号(11位,数字
手机号第一个数字1
^1[3,5,6,7,8,9][0-9]{9}$
正则表达式只用于字符串,可以matches 方法进行匹配
tmp_user_price.matches("^[0-9]+(.[0-9]{1,2})?$")
这里我们写while方法和官方class文件中的内容做对比
第一种:while方法
String tmp_user_price=scanner.next();
//注意while里面匹配小数的正则,不匹配取非(!)
while(!tmp_user_price.matches("^[0-9]+(.[0-9]{1,2})?$")){
System.out.println("你输入的价格有问题,请检查输入价格:");
tmp_user_price=scanner.next();
}
第二种:for的写法
for(tmp_user_price = scanner.next(); !tmp_user_price.matches("^[0-9]+(.[0-9]{1,2})?$"); tmp_user_price = scanner.next()) {
System.out.println("你输入的价格有问题,请检查输入价格:");
}
这里基本我们这里的while,在class字节文件中都转化成了for
循环的思路:
把需要循环放在循环体里,确定好循环的条件,确定循环次数使用for,不确定循环次数使用while,可以效仿class文件,所有的循环都用for解决
While循环里套用另个一个while,或者是for循环中套用另外一个for,这就是循环嵌套.
这里我们写一个switch
switch(user_choice){
case "1":
//只能产生整数,不需要round,经过round计算后是double类型,当前plan_price也不是两位小数
//需要用到格式化的方法,先把Math.random()*1000+1000变成字符串,字符串转化成%f,保留两位小数
//这里先产生一个临时的字符串,可以调用String.format,使用%.2f
String tmp_price=String.format("%.2f",Math.random()*1000+1000);
//之后再把tmp_price转化成float类型,不同类型之间转换调用类型的大写.parse类型
plan_price=Float.parseFloat(tmp_price);
// System.out.println(plan_price);
break;
case "2":
//先定义一个临时变量,格式化字符串两位小数
tmp_price=String.format("%.2f",Math.random()*99+1);
//再使用Float.parseFloat不同类型之间转化方法转化成float类型
plan_price=Float.parseFloat(tmp_price);
// System.out.println(plan_price);
break;
default:
//先定义一个临时变量,格式化字符串两位小数
tmp_price=String.format("%.2f",Math.random()*10000);
//再使用Float.parseFloat不同类型之间转化方法转化成float类型
plan_price=Float.parseFloat(tmp_price);
}
字节文件添加一个byte的中间变量
byte var6 = -1;
switch(user_choice.hashCode()) {
case 49:
if (user_choice.equals("1")) {
var6 = 0;
}
break;
case 50:
if (user_choice.equals("2")) {
var6 = 1;
}
}
给这个中间变量0和-1,然后根据中间变量做代码中的逻辑
switch(var6) {
case 0:
tmp_price = String.format("%.2f", Math.random() * 1000.0D + 1000.0D);
plan_price = Float.parseFloat(tmp_price);
break;
case 1:
tmp_price = String.format("%.2f", Math.random() * 99.0D + 1.0D);
plan_price = Float.parseFloat(tmp_price);
break;
default:
tmp_price = String.format("%.2f", Math.random() * 10000.0D);
plan_price = Float.parseFloat(tmp_price);
}
精典程序:九九乘法法
思想:用循环解决各种形状问题
(1)
*
* *
* * *
(2)
*
* *
* * * *
* * * * * *
(3)九九乘法表的形状
1*1=1
1*2=2 2*2=4
1*3=3 2*3=6 3*3=9
思想:
- 这里面有两个数相乘,产生两个数
1-9乘以1-9,这里未知数是两个,这两个数字交叉相叉。
凡是思想中存在两值交叉的现象,就是双重循环
两个交叉相乘属于笛卡尔积
构建出来
调整结构
分出行和列的关系
打印的几种函数:
Println实现的效果:每打印一行,就换行,
Print实现的效果:不换行
Printf 按某种格式输出,使用format格式化的形式输出,不换行
打印过程中的转义字符
需要代表某些特殊意义的字符,称为转义字符
比如两个数据之间长空白(8个) 制表符 \t
还比如 \n 实现换行
最麻烦的”” ,在java编程中,单引号和双引号都有特殊意义,双引号内部输出双引号,可以使用转义\,加上一个引号
System.out.print("\"");
如果输出斜杠,使用两个斜杠.
System.out.print("\\");
原来
1*1=1 1*2=2 1*3=3 行,转成列
第一个乘数是i,第二个乘数是j
根据打印的结果,j<=i的就打印结果,j>i的就不打印结果
代码如下:
public class test_nine_nine_multi {
public static void main(String[] args) {
//产生笛卡尔积相乘的两个数字,这就是双重循环
for(int i=1;i<10;i++){
for(int j=1;j<10;j++){
//满足条件的打印,根据去掉部分的特点,j>i的不打印,只打印j<=i
//注意第一个乘数是i,第二个乘数是j,调用位置相当于把行列调换
if(j<=i){
System.out.print(j+"*"+i+"="+i*j+"\t");
}
}
//每打完9个数字,换个行,第一重循环结束打印换行
System.out.println();
}
}
}
正向思路:
只要j>i就使用break退出
public class test_nine_nine_multi1 {
public static void main(String[] args) {
//产生笛卡尔积相乘的两个数字,这就是双重循环
for(int i=1;i<10;i++){
for(int j=1;j<10;j++){
//满足条件的打印,根据去掉部分的特点,j>i的不打印,后面的都不打印,节省循环,可以直接退出循环
if(j>i){
//这里break退出,只要打印列数>行数,后面就不循环了,这种方法循环次数会少一些
break;
}
//注意第一个乘数是i,第二个乘数是j,调用位置相当于把行列调换
System.out.print(j+"*"+i+"="+i*j+"\t");
}
//每打完9个数字,换个行,第一重循环结束打印换行
System.out.println();
}
}
}
这个程序比上一次程序循环次数减少.
现在再改,如果j==i,打印完当次结果,就没有必要再进入循环体,再进入循环体也就是判断退出,把j==i条件放在打印的后面.
最后再优化,把j==i后面的循环都不进行操作,这种量级减少循环
public class test_nine_nine_multi2 {
public static void main(String[] args) {
//产生笛卡尔积相乘的两个数字,这就是双重循环
for(int i=1;i<10;i++){
for(int j=1;j<10;j++){
//注意第一个乘数是i,第二个乘数是j,调用位置相当于把行列调换
System.out.print(j+"*"+i+"="+i*j+"\t");
//满足条件的打印,根据去掉部分的特点,j=i的打印结束,后面的循环没有必要了
if(j==i){
//这里break退出,后面的循环完全没有必要
break;
}
}
//每打完9个数字,换个行,第一重循环结束打印换行
System.out.println();
}
}
}
对比class字节的处理
for(int i = 1; i < 10; ++i) {
for(int j = 1; j < 10 && j <= i; ++j) {
System.out.print(j + "*" + i + "=" + i * j + "\t");
}
System.out.println();
}
这种比上面的代码还科学
算法的大O
第一种双重循环,达到某一条件打印: O(n平方 )
第二种双重循环:<o的平方结果的一半
第三种双重循环,比第二重循环少了外层量级的循环次数
在多重循环中,考虑内层循环是否可以再量级减少循环次数.
break退出,退出一层循环,改变当前层的循环次数
continue退出:退出当前循环的次数,继续下次循环,不改变总体的循环次数
共同点:都不执行循环体中后面的语句
不同点:continue结束当前,break结束本层循环