OO第一次大作业
前言
前言的前言
这是我的第一篇blog,有点小激动,我还找教程设置了一下我的背景,本来还想弄个页面小宠物,但是看了一下感觉有点复杂,下次一定。如果对我blog的内容有任何修正或者建议可以评论让我知道,谢谢你愿意点开我的blog并给出建议🌹。
第一次作业
涉及知识点
基本数据类型、顺序结构、选择结构、循环结构、字符串、数组、数论、模拟。
题量
一共12题,看起来题量很大的样子,但是除了第10题,其他题目都比较简单,涉及的知识点也比较广泛,应该是为了让我们熟悉Java的基本语法,并没有出现类的使用。
难度
如上面所说的,除了第10题,其他题目都还是比较简单的,但是有一些小细节的地方也很容易出错,导致卡题。
关于题目的一些观点
1、对于第10题,我想多说两句,对于第10题使用的算法还是比较简单的,就是用String的一些基本操作,对处理过程进行模拟,我觉得第10题的难点主要还是在题目的理解上。
2、第11题我觉得不是很合理(个人观点,不喜勿喷),根据我的理解,题目应该是想要我们模拟定积分的运算过程。我先用高数知识直接对它积分,算出的结果很完美的通过了测试点。然后我按照题目的意思进行模拟,却一个点都没过,我知道模拟的结果会存在很大的误差,但我还是认为这个测试点不太符合题目想表达的意思。当然不排除我程序写错的可能性(后续有对拍的测试说明)。
第二次作业
涉及知识点
基本数据类型、数组、顺序结构、选择结构、字符串、模拟。
题量
一共9题,对比第一次作业题量少了,但是难度没有上升,应该还是为了让我们熟悉Java的基本语法。并且这次作业,每一个题目都有选择结构,我认为是一个对选择结构的强化训练。
难度
好玩不难,但是因为精度的问题被卡了好几题,最难的点我觉得是第8题中出现的浮点误差。值得一提的是,出现了需要写多个方法来解决问题的题目。
第三次作业
涉及知识点
构造类、LocalDate、顺序结构、选择结构、读类图。
题量
一共4题,题目量是最少的,第一次要求构造类,并且全部都是需要构造类,应该是关于构造类的强化训练。
难度
我个人认为难度一下就上来了,可能是我那时候还太不会构造类,虽然上课讲了,线上课程也有演示,但要我自己写的时候,一开始还是有点迷茫,不知道该怎么做。
三次作业总结
第一、二次作业都比较简单,题量比较大,旨在熟悉Java的语法。第三次作业难度就上来了,虽然题目量小,但花的时间是最多的,目的是熟悉怎么构造类。
设计与分析
写在前面
我主要是分析了第三次作业的代码的情况,因为第一次和第二次都只有主类和主方法,并且我在下面的踩坑心得里写的比较详细了。
7-1
源码数据

类图

源码
import java.util.Scanner;
class Circle{
private double radius;
public Circle(){
}
public Circle(double radius){
this.radius = radius;
}
public double getter(){
return this.radius;
}
public double setter(double radius) {
return this.radius = radius;
}
public double getArea(){
return Math.PI * Math.pow(this.radius,2);
}
}
public class Main{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
double r = input.nextDouble();
Circle circle = new Circle(r);
if(r < 0)
System.out.println("Wrong Format");
else{
//circle.setter(r);
System.out.printf("The circle's radius is:%.2f\n",circle.getter());
System.out.printf("The circle's area is:%.2f\n",circle.getArea());
}
}
}
浅说几句
第一次用类来写程序,真的很煎熬,虽然听了老师的课,但是写起来还是不会,就只能又打开视频,跟着老师的讲解来模仿。画类图的时候,我发现我的setter居然是double类型,QAQ充分体现了初学者的憨憨操作。而且由于pta的特性,类只能在Main.java中构造,又在网上看了几篇文章才知道应该怎么写🥀。
7-2
源码数据

类图

源码
import java.util.Scanner;
import java.time.LocalDate;
class Account{
private int id = 0;
private double balance = 0.0;
private double annualInterestRate = 0.0;
private LocalDate dateCreated = LocalDate.of(2020,7,31);
public Account(){
}
public Account(int id,double balance){
this.id = id;
this.balance = balance;
}
public int getId(){
return this.id;
}
public void setId(int id){
this.id = id;
}
public double getBalance(){
return this.balance;
}
public void setBalance(double balance){
this.balance = balance;
}
public double getAnnuallnterstRate(){
return this.annualInterestRate;
}
public void setAnnuallnteratRate(double annualInterestRate){
this.annualInterestRate = annualInterestRate;
}
public LocalDate getDateCreated(){
return this.dateCreated;
}
public double getMonthlyInterestRate(){
return (this.annualInterestRate / 1200) * this.balance;
}
public void withDraw(double getMoney){
this.balance -= getMoney;
}
public void deposit(double bankMoney){
this.balance += bankMoney;
}
}
public class Main{
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int id = input.nextInt();
double balance = input.nextDouble();
double annualInterestRate = input.nextDouble();
double getMoney = input.nextDouble();
double bankMoney = input.nextDouble();
Account account = new Account(id,balance);
//account.setId(id);
//account.setBalance(balance);
account.setAnnuallnteratRate(annualInterestRate);
if(getMoney < 0 || getMoney > account.getBalance())
System.out.println("WithDraw Amount Wrong");
else
account.withDraw(getMoney);
if(bankMoney > 20000 || bankMoney < 0)
System.out.println("Deposit Amount Wrong");
else
account.deposit(bankMoney);
System.out.printf("The Account'balance:%.2f\n",account.getBalance());
System.out.printf("The Monthly interest:%.2f\n",account.getMonthlyInterestRate());
System.out.println("The Account'dateCreated:" + account.getDateCreated());
}
}
浅说几句
这个程序写的时候明显比第一题顺手一点,有参和无参的构造方法都试着用了一下。浅浅了解了一下LocalDate这个类,发出了"Java好方便"的感叹。最后还想提一下运算的一个小坑(有同学被坑了),a * b / c 和 a * (b / c)在数学里面是一样的结果,但是在计算机里是不一样的,我个人认为也是浮点误差造成的,如果有不同的见解,欢迎评论🌹。
7-3
源码数据

类图

源码
import java.util.Scanner;
class Date{
private int year;
private int month;
private int day;
public int[] mon_maxnum = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
public Date(){
}
public Date(int year,int month,int day){
this.year = year;
this.month = month;
this.day = day;
}
public int getYear(){
return this.year;
}
public void setYear(int year){
this.year = year;
}
public int getMonth(){
return this.month;
}
public void setMonth(int month){
this.month = month;
}
public int getDay(){
return this.day;
}
public void setDay(int day){
this.day = day;
}
public boolean isLeapYear(int year){
if(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)){
mon_maxnum[2]++;
return true;
}
else return false;
}
public boolean checkInputValidity(){
if(this.year < 1900 || this.year > 2000)
return false;
else if(this.month < 1 || this.month > 12)
return false;
else if(this.day < 1 || this.day > mon_maxnum[month])
return false;
else return true;
}
public void getNextDate(){
if(this.day + 1 > mon_maxnum[month])
{
this.day = 1;
if(this.month < 12)
this.month++;
else{
this.month = 1;
this.year++;
}
}
else this.day++;
}
}
public class Main {
public static void main(String[] args){
Scanner input = new Scanner(System.in);
int year = input.nextInt();
int month = input.nextInt();
int day = input.nextInt();
Date date = new Date(year,month,day);
//date.setYear(year);
//date.setMonth(month);
//date.setDay(day);
date.isLeapYear(year);
if(!date.checkInputValidity()){
System.out.println("Date Format is Wrong");
}
else {
date.getNextDate();
System.out.println("Next day is:" + date.getYear() + "-" + date.getMonth() + "-" + date.getDay());
}
}
}
浅说几句
这个题跟第二次作业的最后一题原理基本相同,就是把日期封装成了类,这题我也尝试了两种构造方法,都是OK的。
7-4
源码数据

类图

源码
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int year = 0;
int month = 0;
int day = 0;
int choice = input.nextInt();
if (choice == 1) { // test getNextNDays method
int m = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
DateUtil date = new DateUtil(year, month, day);
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}
m = input.nextInt();
if (m < 0) {
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
System.out.println(date.getNextNDays(m).showDate());
} else if (choice == 2) { // test getPreviousNDays method
int n = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
DateUtil date = new DateUtil(year, month, day);
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}
n = input.nextInt();
if (n < 0) {
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(
date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
System.out.println(date.getPreviousNDays(n).showDate());
} else if (choice == 3) { //test getDaysofDates method
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
int anotherYear = Integer.parseInt(input.next());
int anotherMonth = Integer.parseInt(input.next());
int anotherDay = Integer.parseInt(input.next());
DateUtil fromDate = new DateUtil(year, month, day);
DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
System.out.println("The days between " + fromDate.showDate() +
" and " + toDate.showDate() + " are:"
+ fromDate.getDaysofDates(toDate));
} else {
System.out.println("Wrong Format");
System.exit(0);
}
}
else{
System.out.println("Wrong Format");
System.exit(0);
}
}
}
class DateUtil{
private int year;
private int month;
private int day;
protected int[] mon_maxnum = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
public DateUtil(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return this.year;
}
public void setYear(int year){
this.year = year;
}
public int getMonth() {
return this.month;
}
public void setMonth(int month){
this.month = month;
}
public int getDay() {
return this.day;
}
public void setDay(int day){
this.day = day;
}
public String showDate(){
return this.year + "-" + this.month + "-" + this.day;
}
public boolean checkInputValidity(){
if(year < 1820 || year > 2020)
return false;
else if(month < 1 || month > 12)
return false;
else if(day < 1 || day > mon_maxnum[month])
return false;
else return true;
}
public boolean isLeapYear(int year){
if(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)){
mon_maxnum[2] = 29;
return true;
}
else {
mon_maxnum[2] = 28;
return false;
}
}
public DateUtil getNextNDays(int n){
//DateUtil date = new DateUtil(this.year,this.month,this.day);
isLeapYear(this.year);
while (n > 0){
for(int i = this.month;i <= 12;i++) {
if (n - (mon_maxnum[i] - this.day + 1) > 0) {
this.month += 1;
if (this.month > 12) {
this.month -= 12;
this.year += 1;
isLeapYear(this.year);
}
n -= mon_maxnum[i] - this.day + 1;
this.day = 1;
} else {
this.day += n;
n -= n;
break;
}
}
}
return this;
}
public DateUtil getPreviousNDays(int n){
isLeapYear(this.year);
while (n > 0){
for(int i = this.month;i >= 1;i--) {
if (n - this.day > 0) {
this.month -= 1;
if (this.month < 1) {
this.month += 12;
this.year -= 1;
isLeapYear(this.year);
}
n -= this.day;
this.day = mon_maxnum[this.month];
}
else {
this.day -= n;
n -= n;
break;
}
}
}
return this;
}
public boolean compareDates(DateUtil date){
if(this.year > date.year)
return true;
else if(this.year < date.year)
return false;
else {
if(this.month > date.month)
return true;
else if(this.month < date.month)
return false;
else {
if(this.day > date.day)
return true;
else if(this.day < date.day)
return false;
else return false;
}
}
}
public boolean equalTwoDates(DateUtil date){
if(this.year == date.year && this.month == date.month && this.day == date.day)
return true;
else return false;
}
public int getDaysofDates(DateUtil date){
int sum1 = 0,sum2 = 0;
int year = Math.min(date.year,this.year);
int month = 1;
int day = 1;
if(equalTwoDates(date)) {
return sum2 - sum1;
}
else {
for (int i = year; i < date.year; i++) {
if (isLeapYear(i)) {
sum1 += 366;
} else sum1 += 365;
}
sum1 += date.day;
isLeapYear(date.year);
for(int i = 1;i < date.month;i++) {
sum1 += mon_maxnum[i];
}
for (int i = year; i < this.year; i++) {
if (isLeapYear(i)) {
sum2 += 366;
} else sum2 += 365;
}
sum2 += this.day;
isLeapYear(this.year);
for (int i = month; i < this.month; i++) {
sum2 += mon_maxnum[month];
}
//System.out.println(sum2 + " " + sum1);
return Math.abs(sum2 - sum1);
}
}
}
浅说几句
这题是上一题的升级版,看起来很复杂,但是只要把问题拆分,变成三个问题,再逐一解决,就会简单一些。这题时间给的比较宽泛,所以计算前n天和后n天我都是前让日期加或减到下个月的第一天和前一个月的最后一天,然后再逐月处理。在跨年和二月的处理上遇到了一点问题,但是调试过程中很快就能发现。两天之差的计算出现的问题比较大,一开始我的算法是以较前的日期为起点,将计算后n天的代码,处理后逆用。幻想很美好,现实很残酷,计算结果跟样例差距很大。在跟一个实力远强于我的同学讨论后,发现可以沿用之前写过的计算时间差的题目的方法,以较前的年份的1月1日为起点,逐月分别计算到两个日期经过的天数,相减就是两个日期的天数差。
再说几句
这题有比较多同学找我帮了忙,我也从中发现了一些问题:
1、数据最大时,有的算法会超过int的范围,可以转用long存储,最后再转换成int
2、在判断闰年的时候,被判断的年份,到底是当年份还是最开始的年份
3、不是闰年时,2月的天数是否还原成28天
后期发现的问题
在进行第4次迭代的时候,发现了一些问题,这里对问题进行一下展示,给一份更新后的代码

很明显3月0日是不存在的,修改后如图

更新后的代码:
import java.util.Scanner;
public class Main {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
int year = 0;
int month = 0;
int day = 0;
int choice = input.nextInt();
if (choice == 1) { // test getNextNDays method
int m = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
DateUtil date = new DateUtil(year, month, day);
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}
m = input.nextInt();
if (m < 0) {
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " next " + m + " days is:");
System.out.println(date.getNextNDays(m).showDate());
} else if (choice == 2) { // test getPreviousNDays method
int n = 0;
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
DateUtil date = new DateUtil(year, month, day);
if (!date.checkInputValidity()) {
System.out.println("Wrong Format");
System.exit(0);
}
n = input.nextInt();
if (n < 0) {
System.out.println("Wrong Format");
System.exit(0);
}
System.out.print(
date.getYear() + "-" + date.getMonth() + "-" + date.getDay() + " previous " + n + " days is:");
System.out.println(date.getPreviousNDays(n).showDate());
} else if (choice == 3) { //test getDaysofDates method
year = Integer.parseInt(input.next());
month = Integer.parseInt(input.next());
day = Integer.parseInt(input.next());
int anotherYear = Integer.parseInt(input.next());
int anotherMonth = Integer.parseInt(input.next());
int anotherDay = Integer.parseInt(input.next());
DateUtil fromDate = new DateUtil(year, month, day);
DateUtil toDate = new DateUtil(anotherYear, anotherMonth, anotherDay);
if (fromDate.checkInputValidity() && toDate.checkInputValidity()) {
System.out.println("The days between " + fromDate.showDate() +
" and " + toDate.showDate() + " are:"
+ fromDate.getDaysofDates(toDate));
} else {
System.out.println("Wrong Format");
System.exit(0);
}
}
else{
System.out.println("Wrong Format");
System.exit(0);
}
}
}
class DateUtil{
private int year;
private int month;
private int day;
protected int[] mon_maxnum = new int[]{0,31,28,31,30,31,30,31,31,30,31,30,31};
public DateUtil(int year, int month, int day) {
this.year = year;
this.month = month;
this.day = day;
}
public int getYear() {
return this.year;
}
public void setYear(int year){
this.year = year;
}
public int getMonth() {
return this.month;
}
public void setMonth(int month){
this.month = month;
}
public int getDay() {
return this.day;
}
public void setDay(int day){
this.day = day;
}
public String showDate(){
return this.year + "-" + this.month + "-" + this.day;
}
public boolean checkInputValidity(){
if(year < 1820 || year > 2020)
return false;
else if(month < 1 || month > 12)
return false;
else if(day < 1 || day > mon_maxnum[month])
return false;
else return true;
}
public boolean isLeapYear(int year){
if(year % 400 == 0 || (year % 4 == 0 && year % 100 != 0)){
mon_maxnum[2] = 29;
return true;
}
else {
mon_maxnum[2] = 28;
return false;
}
}
public DateUtil getNextNDays(int n){
//DateUtil date = new DateUtil(this.year,this.month,this.day);
isLeapYear(this.year);
while (n > 0){
for(int i = this.month;i <= 12;i++) {
if (n - (mon_maxnum[i] - this.day + 1) > 0) {
this.month += 1;
if (this.month > 12) {
this.month -= 12;
this.year += 1;
isLeapYear(this.year);
}
n -= mon_maxnum[i] - this.day + 1;
this.day = 1;
} else {
this.day += n;
n -= n;
break;
}
}
}
return this;
}
public DateUtil getPreviousNDays(int n){
isLeapYear(this.year);
while (n > 0){
for(int i = this.month;i >= 1;i--) {
if (n - this.day >= 0) {
this.month -= 1;
if (this.month < 1) {
this.month += 12;
this.year -= 1;
isLeapYear(this.year);
}
n -= this.day;
this.day = mon_maxnum[this.month];
}
else {
this.day -= n;
n -= n;
break;
}
}
}
return this;
}
public boolean compareDates(DateUtil date){
if(this.year > date.year)
return true;
else if(this.year < date.year)
return false;
else {
if(this.month > date.month)
return true;
else if(this.month < date.month)
return false;
else {
if(this.day > date.day)
return true;
else if(this.day < date.day)
return false;
else return false;
}
}
}
public boolean equalTwoDates(DateUtil date){
if(this.year == date.year && this.month == date.month && this.day == date.day)
return true;
else return false;
}
public int getDaysofDates(DateUtil date){
int sum1 = 0,sum2 = 0;
int year = Math.min(date.year,this.year);
int month = 1;
int day = 1;
if(equalTwoDates(date)) {
return sum2 - sum1;
}
else {
for (int i = year; i < date.year; i++) {
if (isLeapYear(i)) {
sum1 += 366;
} else sum1 += 365;
}
sum1 += date.day;
isLeapYear(date.year);
for(int i = 1;i < date.month;i++) {
sum1 += mon_maxnum[i];
}
for (int i = year; i < this.year; i++) {
if (isLeapYear(i)) {
sum2 += 366;
} else sum2 += 365;
}
sum2 += this.day;
isLeapYear(this.year);
for (int i = month; i < this.month; i++) {
sum2 += mon_maxnum[month];
}
//System.out.println(sum2 + " " + sum1);
return Math.abs(sum2 - sum1);
}
}
}
踩坑心得
写在前面
我并没有对这三次作业的全部题目进行分析,毕竟有的题目真的很简单,几乎没有出错的地方,所以我只选取了我认为对我来说比较有价值的题目来分析。
第一次作业
7-1
问题
第一题确实不难,但是在控制小数位数卡了好久,题目给的数据计算结果恰好跟保留两位小数的结果一致,导致忽略了保留小数的操作,一直认为是边界值的问题,进行了大量尝试

解释和心得
从我下面的两张图片可以看出来,格式化输出后就好了。这个悲惨的故事告诉我们要仔细看题,理解它的一些潜在信息。我知道我这个代码很不规范(丑陋),已经在改啦!QAQ

import java.util.Scanner;
public class Main
{
public static void main(String [] args)
{
Scanner input = new Scanner(System.in);
long year = input.nextLong();
double ans = 7.70;
if(year <= 0)
{
System.out.print("error");
}
else
{
if(year <= 1)
ans *= 0.5;
else if(year <= 3)
ans *= 0.7;
else if(year <= 5)
ans *= 1.0;
else ans *= 1.1;
System.out.print("实际利率="+ans+"%");
}
}
}
上面是没格式化输出的

import java.util.Scanner;
public class Main
{
public static void main(String [] args)
{
Scanner input = new Scanner(System.in);
long year = input.nextLong();
double ans = 7.70;
if(year <= 0)
{
System.out.print("error");
}
else
{
if(year <= 1)
ans *= 0.5;
else if(year <= 3)
ans *= 0.7;
else if(year <= 5)
ans *= 1.0;
else ans *= 1.1;
System.out.printf("实际利率=%3.2f%%",ans);
}
}
}
上面是格式化输出的,有图有真相!
这里浅说一下%,因为%在printf中有特殊含义,所以要让它反义。如果感兴趣的话,你可以试试怎样才能输出"\x2333 为\a什\b么\r我\n签\n到\r题\b都\a过不了QAQ%",欢迎评论哦!
7-7
问题
在这个题目中,第一次出现“非零返回”,我去搜索了一下,大概了解到:“非零返回”就是程序异常中止,我这里应该是因为数组越界导致堆栈溢出。

解释和心得
为什么会数组溢出呢?我一看到题目就觉得好熟悉,跟桶排序的题目非常像,我就直接桶排序来记录数据出现的次数。后面发现每一个数的范围并没有给出,导致数组越界。
import java.util.Scanner;
public class Main
{
public static void main(String [] args)
{
Scanner input = new Scanner(System.in);
int flag =0;
final int N = 100005;
int [] book = new int [N];
int n = input.nextInt();
int [] arr = new int [n];
for(int i = 0;i < n;i++)
{
arr[i] = input.nextInt();
book[arr[i]]++;
if(book[arr[i]]>1)
flag=1;
}
if(flag == 1)
System.out.print("YES");
else System.out.print("NO");
}
}
桶排序不行,我就开始模拟,果然t了。

import java.util.Scanner;
public class Main
{
public static void main(String [] args)
{
Scanner input = new Scanner(System.in);
int flag =0;
int n = input.nextInt();
int [] arr = new int [n];
for(int i = 0;i < n;i++)
{
arr[i] = input.nextInt();
if(flag == 0)
{
for(int j = 0;j < i;j++)
{
if(arr[j] == arr[i])
{
flag = 1;
break;
}
}
}
}
if(flag == 1)
System.out.print("YES");
else System.out.print("NO");
}
}
很明显这个算法的时间复杂度是O(n^2),不t才怪。联想到C++的sort(),作为C++好兄弟的Java不可能没有吧?

浅浅运用了一下

import java.util.Scanner;
import java.util.Arrays;
public class Main
{
public static void main(String [] args)
{
Scanner input = new Scanner(System.in);
int flag =0;
int n = input.nextInt();
int [] arr = new int [n];
for(int i = 0;i < n;i++)
arr[i] = input.nextInt();
Arrays.sort(arr);
for(int i = 1;i < n;i++)
{
if(arr[i]==arr[i-1])
{
System.out.print("YES");
flag = 1;
break;
}
}
if(flag == 0)
System.out.print("NO");
}
}
7-10
问题:
这题也存在一些读题上的问题,题目明确说了,如果有多条满足题意的,输出最后一次的时间,但我的算法是找到了就输出,直接结束。
解释和心得
这个是错误代码

import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String s;
while (true)
{
int sum = 0,text = 0;
s = input.nextLine();
if (s.equals("END"))
break;
if (s.indexOf("$GPRMC", 0) != -1 && s.indexOf(",A,", 0) != -1) {
text = Integer.parseInt(s.substring(s.indexOf('*') + 1), 16);
for (int i = 1; s.charAt(i) != '*'; i++) {
sum ^= s.charAt(i);
}
if (text == (sum %= 65536)) {
int t = Integer.parseInt(s.substring(s.indexOf(',') + 1, s.indexOf(',') + 7), 10);
//System.out.printf("%06d", t);
int ss = t % 100;
int mm = (t % 10000 - ss) / 100;
int hh = (t - mm * 100 - ss) / 10000 + 8;
if (hh >= 24)
hh -= 24;
System.out.printf("%02d:%02d:%02d", hh, mm, ss);
break;
}
}
}
}
}
正确的代码,就只改了输出的地方

import java.util.Scanner;
public class Main
{
public static void main(String[] args)
{
Scanner input = new Scanner(System.in);
String s;
int ss = 0 , mm = 0 , hh = 0;
while (true)
{
int sum = 0,text = 0;
s = input.nextLine();
if (s.equals("END"))
break;
if (s.indexOf("$GPRMC", 0) != -1 && s.indexOf(",A,", 0) != -1)
{
text = Integer.parseInt(s.substring(s.indexOf('*') + 1), 16);
for (int i = 1; s.charAt(i) != '*'; i++)
{
sum ^= s.charAt(i);
}
if (text == (sum %= 65536))
{
int t = Integer.parseInt(s.substring(s.indexOf(',') + 1, s.indexOf(',') + 7), 10);
//System.out.printf("%06d", t);
ss = t % 100;
mm = (t % 10000 - ss) / 100;
hh = (t - mm * 100 - ss) / 10000 + 8;
if (hh >= 24)
hh -= 24;
}
}
}
System.out.printf("%02d:%02d:%02d", hh, mm, ss);
}
}
这个题目主要是考察对String类里面一些方法的运用,比较:s.equals("")、查找:s.indexOf()、取字符串中的某个字符 s.charAt(i)等等。虽然,后面练习时我又忘了该怎么使用,但我不会像写这个题目一样对它们那么陌生。
7-11
解释和心得
这题本身没有对我来说没有问题,我主要想再说一下前面提到的模拟程序。我拿了两个程序对拍,结果如下图:
切分不那么细的运行结果

切分的更细的运行结果

可以看出来,在切分不够细的时候,两者误差比较大,在切分很细的时候,两者误差很小。我认为,这恰好说明了我的模拟程序是正确的,所以上述“程序存在问题”的情况可以排除。
第二次作业
7-6
问题
这题的问题我觉得主要有三个点,一个是读题,理解题目意思;另一个是在写循环的部分,一定要先计算一次再进循环,否则会导致无法进入循环。(这是我看到的别人的错误写法);最后一个就是近似的判断,由于浮点数在计算机中存储的特性,可知浮点数不能全等(==)。
解释和心得
这个题目,就很怪哈,我按照之前的经验,输出前强制转换了,还是不行。最后是把double全部改float才过的^ ^。

import java.util.Scanner;
public class Main{
public static void main(String [] args){
Scanner input = new Scanner(System.in);
double n = input.nextDouble();
double guess1 = input.nextDouble();
double guess2;
if(n < 0 || guess1 <= 0)
System.out.print("Wrong Format");
else{
guess2 = (guess1 + n / guess1) / 2;
while(Math.abs(guess1 - guess2) >= 0.00001)
{
guess1 = guess2;
guess2 = (guess1 + n / guess1) / 2;
}
System.out.print((float)guess1);
}
}
}

import java.util.Scanner;
public class Main{
public static void main(String [] args){
Scanner input = new Scanner(System.in);
float n = input.nextFloat();
float guess1 = input.nextFloat();
float guess2;
if(n < 0 || guess1 <= 0)
System.out.print("Wrong Format");
else{
guess2 = (guess1 + n / guess1) / 2;
while(Math.abs(guess1 - guess2) >= 0.00001)
{
guess1 = guess2;
guess2 = (guess1 + n / guess1) / 2;
}
System.out.print((float)guess1);
}
}
}
7-8
问题:
我在写的时候主要有两个问题,一个是等腰三角形的判断,另一个是等腰直角三角形的判断。等腰直角三角形的判断就涉及到浮点数判等的情况。
解释和心得
这是错误的代码,可以看到在判断等腰的时候,我只对a,b是否相等进行判断,但是很明显b,c也可能相等。(为什么我不说a,c也可能相等呢?因为我先对a,b,c进行了排序,a是最小的,c是最大的,如果a,c相等,那么b也与a,c相等,这时是等边三角形)在判断等腰直角时,我用的是全等,根据浮点数在计算机中的存储,很明显, Math.pow(c,2) == Math.pow(a,2) + Math.pow(b,2)这个条件是不可能满足的。
import java.util.Scanner;
public class Main{
public static void main(String [] args){
Scanner input = new Scanner(System.in);
float a = input.nextFloat();
float b = input.nextFloat();
float c = input.nextFloat();
if(a < 1 || a > 200 || b < 1 || b > 200 || c < 1 || c > 200){
System.out.println("Wrong Format");
return ;
}
else{
if(a > b){
float t;
t = a;
a = b;
b = t;
}
if(b > c){
float t;
t = b;
b = c;
c = t;
}
if(a > c){
float t;
t = a;
a = c;
c = t;
}
if(a + b <= c || a + c <= b || b + c <= a){
System.out.println("Not a triangle");
return ;
}
if(a == b && b == c){
System.out.println("Equilateral triangle");
return ;
}
if(a == b && Math.pow(c,2) == Math.pow(a,2) + Math.pow(b,2)){
System.out.println("Isosceles right-angled triangle");
return ;
}
if(a == b && Math.pow(c,2) != Math.pow(a,2) + Math.pow(b,2)){
System.out.println("Isosceles triangle");
return ;
}
if(a != b && Math.pow(c,2) == Math.pow(a,2) + Math.pow(b,2)){
System.out.println("Right-angled triangle");
return ;
}
System.out.println("General triangle");
}
}
}
修改后代码如下
import java.util.Scanner;
public class Main{
public static void main(String [] args){
Scanner input = new Scanner(System.in);
float a = input.nextFloat();
float b = input.nextFloat();
float c = input.nextFloat();
if(a < 1 || a > 200 || b < 1 || b > 200 || c < 1 || c > 200){
System.out.println("Wrong Format");
return ;
}
else{
if(a > b){
float t;
t = a;
a = b;
b = t;
}
if(b > c){
float t;
t = b;
b = c;
c = t;
}
if(a > c){
float t;
t = a;
a = c;
c = t;
}
if(a + b <= c || a + c <= b || b + c <= a){
System.out.println("Not a triangle");
return ;
}
if(a == b && b == c){
System.out.println("Equilateral triangle");
return ;
}
if(a == b && Math.abs(a * Math.pow(2,0.5) - c) < 0.000001){
System.out.println("Isosceles right-angled triangle");
return ;
}
if(a == b || b == c || a == c){
System.out.println("Isosceles triangle");
return ;
}
if(a != b && Math.pow(c,2) == Math.pow(a,2) + Math.pow(b,2)){
System.out.println("Right-angled triangle");
return ;
}
System.out.println("General triangle");
}
}
}
运行结果

7-9
问题
这题对我来说还是比较熟悉的,之前做过类似的,一开始就想到了用数组存储每个月的天数,算法也是没有问题的。为什么wa了这么多发呢?全是在调非法输入!!!😭
解释的心得
我最先的代码,可以看到,完全没有考虑到非法输入
import java.util.Scanner;
public class Main{
public static void main(String [] args){
Scanner input = new Scanner(System.in);
int [] arr = {31,28,31,30,31,30,31,31,30,31,30,31};
int year = input.nextInt();
int month = input.nextInt();
int day = input.nextInt();
if((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)){
arr[1]++;
}
if(day + 1 > arr[month - 1]){
day = 1;
if(month < 12)
month++;
else{
year++;
month = 1;
}
}
else{
day++;
}
System.out.println("Next date is:" + year + "-" + month + "-" + day);
}
}
我没有分方法的AC代码
import java.util.Scanner;
public class Main{
public static void main(String [] args){
Scanner input = new Scanner(System.in);
int [] arr = {31,28,31,30,31,30,31,31,30,31,30,31};
int year = input.nextInt();
int month = input.nextInt();
int day = input.nextInt();
if((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0)){
arr[1]++;
}
if(month < 1 || month > 12 || year < 1820 || year > 2020)
System.out.println("Wrong Format");
else{
if(day > arr[month - 1] || day < 1)
System.out.println("Wrong Format");
else{
if(day + 1 > arr[month - 1]){
day = 1;
if(month < 12)
month++;
else{
year++;
month = 1;
}
}
else{
day++;
}
System.out.println("Next date is:" + year + "-" + month + "-" + day);
}
}
}
}
因为那时候还不熟悉怎么调用方法,把主方法拆分后又wa了好几发。

这是我最后的代码,但是在判断这年是闰年之后,让 arr[1]++不好,应该arr[1] = 29,如果不是闰年就arr[1] = 28。
import java.util.Scanner;
public class Main{
public static void main(String [] args){
Scanner input = new Scanner(System.in);
int year = input.nextInt();
int month = input.nextInt();
int day = input.nextInt();
if(checkInputValidity(year,month,day)) {
System.out.println("Wrong Format");
return ;
}
nextDate(year,month,day);
}
public static boolean isLeapYear(int year){
if((year % 400 == 0) || (year % 4 == 0 && year % 100 != 0))
return true;
return false;
}
public static boolean checkInputValidity(int year,int month,int day){
int [] arr = {31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapYear(year))
arr[1]++;
if(month < 1 || month > 12 || year < 1820 || year > 2020 || day < 1 || day > arr[month - 1])
return true;
return false;
}
public static void nextDate(int year,int month,int day){
int [] arr = {31,28,31,30,31,30,31,31,30,31,30,31};
if(isLeapYear(year))
arr[1]++;
if(day + 1 > arr[month - 1]){
day = 1;
if(month < 12)
month++;
else{
year++;
month = 1;
}
}
else{
day++;
}
System.out.println("Next date is:" + year + "-" + month + "-" + day);
}
}
第三次作业
第三次作业在语法上没有遇到什么困难,思路上的在"设计与分析"中说的都差不多了,我就不到这再写一次水字数了。
改进建议
1、第一次作业最大的问题就是,代码规范的问题,看到第二次和第三次作业的代码,能发现我已经在改进了,但还是有一些不足:不打注释,命名不够规范等等。我现在看我之前的代码,我也觉得好丑陋🥀。
2、我觉得我跟同学的交流还是太少了,虽然看起来我的测试点全部都过了,但是有的题目我会在一些小细节的地方出错,自己找bug一直找不到,白白浪费了时间。况且,测试点并不能完全覆盖,也不能测出你的算法优劣,我还是要多跟同学交流,多多学习,当然不仅仅是练习的题目,还有更多的"思维碰撞"。
3、我觉得我现在还是练得太少,学习也不够规范,总是习惯去网上找文章直接看某个知识点,而不是踏踏实实从书上一点点积累。我们现在的教程被叫做"Java字典",我觉得很形象,不认识的"字"就是应该去查"字典"。
4、浅看了一下我的文章,我很多次提到类似"不仔细"的字眼,主要反映在写代码和读题上,或许我应该减少对IDEA实时报错的依赖。
5、要更多的尝试去测试程序的边界,进行一些异常处理,让自己的代码健壮性更强,不会轻易被测试数据打倒💪。
总结
浅浅获得的一些知识
浅浅学会了一点点类的内容,基本的语法之类的。总的来说,我会的东西还是太少了,每次练习都能学到新的东西,这当然很好,能学到新的东西我也很快乐,学习就是一点一滴积累的过程。但我还是比较期待,我发现我好像没有学到什么新东西的那一天。
需要进一步学习的知识
我觉得最需要的就是系统的学习,在空闲的时候应该多花一点时间在看系统的视频课。并且,在学习的过程中最需要的是"知其然,知其所以然"。就像老师说的:"我们学的是专业,哪有那么简单"。
一点小小的建议
1、关于pta的测试点,我有几句想说的:
我认为,结果为小数的答案,应该更加明确,比如规定保留几位小数,或者答案设置成区间,如果用户的数据跟测试点误差小于1e-6就认为相等之类的。在第二次作业中,就有很多题目是因为精确度的问题被卡题。
2、未完,可能再续……
本文来自博客园,作者:clear_tea,转载请注明原文链接:https://www.cnblogs.com/clearTea/p/17249255.html

浙公网安备 33010602011771号