[Java] 实验13

1. 分段函数

1. 用 if - else if - else, 可以表达这三个分支。

2. 保留小数

之所以用 Math.round() 去保留小数,而不是 * 100d / 100, 是因为后者无法处理负数的情况。具体可以参考实验5. 求一元二次方程的根

在此给出保留任意位小数的方法 remainDigits. 

大家应该理解下述原理,自行实现保留两位小数 或 保留任意位小数 的功能。

public class Test {
  public static void main(String[] args) {
    double num = 3.1415926535;
    for (int i = 0; i <= 10; ++ i) {
      System.out.println(remainDigits(num, i));
    }
  }

  static double remainDigits(double num, int digitsToRemain) {
    // e.g. remainDigits(3.14159, 2) was called, then it will return 
    // Math.round(3.14159 * 100d) / 100d, which equals 3.14
    return Math.round(num * Math.pow(10, digitsToRemain)) 
        / Math.pow(10, digitsToRemain);
  }
}

3. 对 System.out.println(double number) 的解释

用 println 输出一个 double 的时候,它总是会忽略这个数值的后导0.

    - 如果 number 的值是一个整数(比如 5.0000),因为它的类型是 double, 那么会输出 5.0;

    - 如果 number 的值是 5.1000, 在保留两位小数后,它会输出 5.1; 

    - 如果 number 的值是 5.1010, 在保留两位小数后,它会输出 5.1.

    - 如果 number 的值是 5.1050, 在保留两位小数后,它会输出 5.11.

这是应该是语法决定的,还望大家不要纠结。

大家只需要关注如何正确地保留两位小数即可。

代码:

public class Test {
  public static void main(String[] args) {
    System.out.println(remainDigits(5.0000, 2));  // Output 5.0
    System.out.println(remainDigits(5.1000, 2));  // Output 5.1
    System.out.println(remainDigits(5.1010, 2));  // Output 5.1
    System.out.println(remainDigits(5.1050, 2));  // Output 5.11
  }

  static double remainDigits(double num, int digitsToRemain) {
    // e.g. remainDigits(3.14159, 2) was called, then it will return 
    // Math.round(3.14159 * 100d) / 100d, which equals 3.14
    return Math.round(num * Math.pow(10, digitsToRemain)) 
        / Math.pow(10, digitsToRemain);
  }
}

2. 输入 2 个正整数 m 和 n, 输出 m 和 n 之间所有能被 7 或 11 整除,但不能被两者同时整除的数。

if ((num % 7 == 0 || num % 11 == 0) && num % 77 != 0) {
  // Print the result here
}

3. 计算近似的 PI


4. 输出从元旦到该日经过的天数

1. 闰年的定义参考 实验 8. 40035 计算某月的天数

2. 这题可以通过定义一个含有 12 个月份的天数的数组 int[] days = { ... }; 

注意,需要根据是否是闰年,修改数组的第 1 个元素;

譬如,求 1月1号 到 3月8号 有多少天,那么只需要从 days[0] + days[1] + 8 - 1 即可。


5. 给学生成绩排降序

排序方法可以参考实验12. 60030 编写排序函数(方法)

在此我假设学生学号为 String 类型,学生成绩为 double 类型。我们要做的是:

    1. 维护两个数组:学号数组 ids 和成绩数组 grades,该数组满足学生 ids[index] 对应的成绩即为 grades[index]. 亦即通过相同的下标,建立学号和成绩的一一对应关系。

    2. 在给成绩降序排序的同时,维护这个一一对应关系:如果在成绩数组中交换了元素 grades[i] 和 grades[j]. 那么我们也在学号数组中,交换 ids[i] 和 ids[j].

假设题目输入满足下列格式:

3
3150100001 86.5
3150100002 88.5
3150100003 87.5
我们的程序可以写成:

// Assume the input has the format like this:
// student_number
// student1_id grade
// student2_id grade
// ...

import java.util.Scanner;

public class GradeSort {
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);

    // Input
    int studentNumber = in.nextInt();
    // Use "String" instead of "int" to represent the student ID,
    // in case it might larger than the maximal value "int" can hold
    String[] ids = new String[studentNumber];
    // Use "double" to represent the student grade
    // in case it might be a floating-point instead of an integer.
    double[] grades = new double[studentNumber];
    for (int i = 0; i < studentNumber; ++ i) {
      ids[i] = in.next();  // Input String
      grades[i] = in.nextDouble();  // Input double
    }

    // Bubble sort
    bubbleSort(ids, grades);

    // Output
    for (String id: ids)
      System.out.println(id);
  }

  static void bubbleSort(String[] ids, double[] grades) {
    for (int i = 1; i < grades.length; ++ i) {
      for (int j = i; j >= 1; -- j) {
        if (grades[j] > grades[j - 1]) {
          swap(grades, j, j -1);
          swap(ids, j, j - 1);
        }
      }
    }
  }

  // Note that we could use the "generic" property to implement ONLY ONE
  // swap method here, while this property is beyond your course requirement.

  static void swap(String[] ids, int i, int j) {
    String temp = ids[i];
    ids[i] = ids[j];
    ids[j] = temp;
  }

  static void swap(double[] grades, int i, int j) {
    double temp = grades[i];
    grades[i] = grades[j];
    grades[j] = temp;
  }
}


6. 计算最大数的出现次数

for (int x = in.nextInt(); x != 0; x = in.nextInt()) {
  // Do your statistics here.
}


7. 回文素数

在此没有引入 String 类,这样使得要解决这题,不需要依赖(记住)其他方法 (method), 只依赖更为基础的编程知识。

我们可以通过下述方法,判断一个数,比如说数字 32123 是否为回文:

    - 通过 32123 / 10000, 取最左边的数字 3, 通过 32123 % 10 取最右边的数字 3. 比较这两个数字是否相同

    - 拿掉最左边和最右边的数字 3,数字变成 212. 通过 212 / 100, 取最左边的数字 2, 通过 212 % 10 取最右边的数字 2. 比较这两个数字是否相同

    - 拿掉最左边和最右边的数字 2,数字变成 1. 所以这是一个回文数。

public class PalindromicPrime {
  public static void main(String[] args) {
    for (int i = 2, count = 0; count < 50; ++ i)
      if (prime(i) && palindrome(i)) {
        System.out.print(i + " " 
          + (++ count % 10 == 0? "\n": ""));
      }
  }
  
  // Determine whether a number is prime or not
  static boolean prime(int num) {
    for (int i = 2; i <= Math.sqrt(num); ++ i)
      if (num % i == 0)
        return false;
    return true;
  }

  // Determine whether a number is palindromic or not
  static boolean palindrome(int num) {
    int digitNum = 1;
    for (int temp = num / 10; temp != 0; temp /= 10)
      ++ digitNum;
    // Thus num has # of digitNum digits
    // e.g. Number 0 has 1 digit, digitNum = 1
    //      Number 52 has 2 digits, digitNum = 2
    //      Number 123 has 3 digits, digitNum = 3
    while (digitNum > 1) {
      int leftmostDigit = (int) (num / Math.pow(10, digitNum - 1));
      int rightmostDigit = num % 10;
      if (leftmostDigit != rightmostDigit)
        return false;
      num =  (num % (int)Math.pow(10, digitNum - 1)) / 10;
      digitNum = digitNum - 2;
    }
    return true;
  }
}


9. 显示素数因子

public class PrimeFactor {
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int num = in.nextInt();
    for (int i = num; i != 1; -- i)
      if (prime(i))
        for (; num % i == 0; num /= i)
          System.out.print(i + " ");        
    in.close();
  }
  
  // Determine whether a number is prime or not  
  static boolean prime(int num) {  
    for (int i = 2; i <= Math.sqrt(num); ++ i)  
      if (num % i == 0)  
        return false;  
    return true;  
  }    
}

10. 统计在字符串中每个数字出现的次数

1. int 数组中每个元素的默认值是 0, 原因可以参考 实验5. Q10

2. 代码:

public static int[] count(String s) {
  int[] res = new int[10];
  for (int i = 0; i < s.length(); ++ i)
    if (s.charAt(i) >= '0' && s.charAt(i) <= '9')
      ++ res[s.charAt(i) - '0'];
  return res;
}


13. 计算两个日期间的天数,并以二进制形式输出

在此我们把问题简化为:

    - 计算给定 year1, yaer2 中间那些年份的日期 days1

    - 计算 year1/month1/day1 到年终的那段日期 days2

    - 计算 year2/month2/day2 距离该年元旦已经过的日期 days3

days1 + days2 + days3 即为所得。

注意到,上述方法可以处理所有情况。

import java.util.Scanner;

public class Days {
  public static void main(String[] args) {
    // Input
    Scanner in = new Scanner(System.in);
    int year1 = in.nextInt();
    int month1 = in.nextInt();
    int day1 = in.nextInt();
    int year2 = in.nextInt();
    int month2 = in.nextInt();
    int day2 = in.nextInt();
    in.close();
    
    // Begin calculation
    int sum = 0;
    
    if (year1 != year2) {
      // Days between [(year1+1)/01/01, (year2-1)/12/lastDay]
      for (int i = year1 + 1; i < year2; ++i)
        sum += leapYear(i) ? 366 : 365;
      // Days between [year1/month1/day1, year1/12/lastDay]
      sum += (leapYear(year1) ? 366 : 365) - (days(year1, month1, day1) - 1);      
      // Days between [year2/01/01, year2/month2/day2]
      sum += days(year2, month2, day2);
    } else {
      sum = days(year2, month2, day2) - days(year1, month1, day1) + 1;
    }
    
    // Output the result
    decToBin(sum);
  }

  private static boolean leapYear(int year) {
    return year % 400 == 0 || (year % 4 == 0 && year % 100 != 0);
  }

  // Days between [year/01/01, year/month/day]
  // i.e. days(2016, 03, 01) = 31 + 29 + 1 = 61
  private static int days(int year, int month, int day) {
    int sum = 0;
    int[] daysInMonth = { 31, leapYear(year) ? 29 : 28, 31, 30, 31, 30, 31, 31,
        30, 31, 30, 31 };
    for (int i = 0; i < month - 1; ++i)
      sum += daysInMonth[i];
    return sum + day;
  }
  
  // Note that we're going to solve this problem recursively (递归地解决问题)  
  // Decimal to binary  
  private static void decToBin(int n) {  
    if (n != 0) {  
      // Print the higher bit first  
      decToBin(n >> 1);  
      // Then print the lower bit  
      System.out.print(n % 2);  
    }  
  }  
}



14. 数字加密

a. 学习简单的数字加密有什么用?

学习数字加密,我们可以比较好的保护自己的信息安全:

    - 对于每个网站,我们的密码可以由 公共前缀(prefix) + 特殊后缀(postfix) 组成

    - 我们对后缀进行加密,得到新的字符串 prefix + encrypt(postfix), 将它作为我们的密码。

    - 而在记录本中,我们只记录自己的 prefix 和 postfix. 

由于加密算法由我们唯一拥有,所以即使这个记录本被别人拿走了,他们仍然无法猜出我们的密码;

不仅如此,我们的每个网站都有着唯一的密码 (你们的助教就是这么做的;)

b. 回到原题

代码如下:

import java.util.Scanner;

public class Encrption {
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    String num1 = in.next();
    String num2 = in.next();
    String result = "";
    char[] table = {'0', '1', '2', '3', '4', '5', '6', '7', '8', '9', 'J', 'Q',
        'K' };
    int i = num1.length() - 1, j = num2.length() - 1;    
    for (boolean isOdd = true; i >= 0 && j >= 0; -- i, -- j, isOdd = !isOdd) {
      if (isOdd) {
        int num = (num1.charAt(i) - '0' + num2.charAt(j) - '0') % 13;
        result = table[num] + result;
      } else {
        int num = num2.charAt(j) - num1.charAt(i);
        num = num > 0? num: num + 10;
        result = table[num] + result;
      }
    }
    for (; j >= 0; -- j) result = table[num2.charAt(j) - '0'] + result;
    System.out.println(result);
    in.close();
  }
}

---------------------------------------------------------------------------------------------------------------------------------------------------------------------------

一下题目为 10.77.30.33 网上的实验 13, 应该是不要求完成的。

70001 

参考《Java语言程序设计--基础篇》:

    - 8.1 引言

    - 8.2 定义对象的类。简单描述了语法规则

    - 8.3 举例:定义类和创建对象。以 Circle 为例。

代码填空:

import java.util.*;

public class CircleTest {
  public static void main(String args[]) {
    Scanner in = new Scanner(System.in);
    int repeat= in.nextInt();
    while (repeat-- != 0) {
      float radius = in.nextFloat();
      Circle cir = new Circle();
      cir.setRadius(radius);
      System.out.println(Math.round(cir.area()));
      System.out.println(Math.round(cir.perimeter()));
    }
    in.close();
  }  
}

class Circle {  
  void setRadius(float radius) {
    radius_ = radius;
  }
  
  // According to the problem specification, the type of the return value 
  // should be double
  double area() {
    ?
  }

  // According to the problem specification, the type of the return value 
  // should be double
  double perimeter() {
    ?
  }
  
  float radius_;
}

70002 设计一个立方体类

基础和代码参考 70001. 

同时注意到,我们在此不像 70001 那样,编写一个 CircleTest 放 main, 另一个 Circle 类放其他方法。事实上,我们只需要一个 Cube 就可以完成题目要求。(70001 也只需要一个 Circle 类,也是可以完成要求——只要把 public static void main 也放进 Circle 中即可)

代码填空:

import java.util.Scanner;

public class Cube {
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    double length = in.nextDouble();
    System.out.println("Length=" + cube1.getLength());
    System.out.println("Surface area=" + cube1.calcArea());
    System.out.println("Volume=" + cube1.calcV());
  }
  
  ? setLength(?) {
    ?
  }
  
  ? getLength(?) {
    ?
  }
  
  // Define your calcArea here
  ?
      
  // Define your calcVolume here
  ?
  
  double length_;
}

70011 设计一个Circle的子类——圆柱体Cylinder

参考《Java语言程序设计--基础篇》,第 11 章 继承和多态:

    - 11.1 引言

    - 11.2 父类和子类。给出了父类与子类的图例,同时给出了相应的代码实现

程序填空:

import java.util.Scanner;

public class CylinderTest {
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    double x = in.nextDouble();
    double y = in.nextDouble();
    double r = in.nextDouble();
    double h = in.nextDouble();
    // Note that we just ignore the x, y, whose reason has been explained 
    // in line 21.
    Cylinder cy = new Cylinder(r, h);
    System.out.println("r=" + cy.getRadius());
    System.out.println("h=" + cy.getHeight());
    System.out.println("V=" + Math.round(cy.calcVolume() * 100) / 100.);
    System.out.println("S=" + Math.round(cy.calcArea() * 100) / 100.);
  }
}

class Circle {
  // The reason we abandon x, y here is we are NOT gonna use them actually
  public Circle(double r) {
    // Thus for a circle, the only information needed to remain is its radius
    this.radius_ = r;
  }

  // Calculate the perimeter for this circle
  public double perimeter() {
    return 2 * Math.PI * radius_;
  }

  // Calculate the area for this circle
  public double area() {
    return Math.PI * radius_ * radius_;
  }

  public double getRadius() {
    return radius_;
  }

  private double radius_;
}

class Cylinder extends Circle {
  Cylinder(double radius, double height) {
    // Call its parent's constructor, Circle(radius), by calling super(radius)
    super(radius);
    // Initialize its own filed
    height_ = height;
  }

  // Define your calcArea here
  ?
      
  // Define your calcVolumn here
  ?

  // Define your getHeight here
  ?

  private double height_;
}

70012 编写重载方法,求二个数或三个数的最大值

import java.util.Scanner;

public class CompareTest {
  public static void main(String[] args) {
    Scanner in = new Scanner(System.in);
    int repeat = in.nextInt();
    while (repeat-- != 0) {
      int a = in.nextInt();
      int b = in.nextInt();
      int c = in.nextInt();
      System.out.println("max(a,b)=" + Compare.max(a, b));
      System.out.println("max(a,b,c)=" + Compare.max(a, b, c));
    }
    in.close();
  }
}

class Compare {
  static int max(int a, int b) {
    ?
  }
  
  static int max(int a, int b, int c) {
    ?
  }
}


  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值