实验I:体验神奇的算法
本实验要求根据给定的正整数n计算第n个斐波那契数。课堂上已经讲过4种不同的算法,请选择自己最熟悉的编程语言实现这些算法来体验算法求解问题的神奇,下列基本要求必须完成:
- 设计一个交互界面(例如菜单)供用户选择,如果可能,最好是一个图形化用户界面。
- 利用迭代算法寻找不超过编程环境能够支持的最大整数的斐波那契数是第几个斐波那契数。(Java: 231-1 for int, 263-1 for long)
- 根据第二步计算的最大的斐波那契数序号n,采用递归方式计算第n个斐波那契数,看其是否可以在1分钟内完成。
- 利用递归算法计算你的计算机能够在30秒内计算出的最大斐波那契数是第几个,计算出下一个斐波那契数的时间是多少,利用迭代算法求解同样的问题。
- 利用公式F(n) = [fn/sqrt(5)]快速计算第n个斐波那契数,找出出现误差时的最小n值。
- 利用矩阵相乘方法计算第n个斐波那契数。
- 对于相同的输入n值,比较上述四种方法的基本操作次数,以掌握对数、线性和指数增长率的极大差别。
Algorithm.java
package com;
//四种算法
public class Algorithm {
//递归算法
public static int fibonacciRecursive(int n) {
if (n == 0) {
return 0;
} else if (n == 1) {
return 1;
} else {
return fibonacciRecursive(n - 1) + fibonacciRecursive(n - 2);
}
}
//迭代算法 O(n)
public static int fibonacciIterative(int n) {
if (n <= 1) {
return n;
}
int a = 0;
int b = 1;
for (int i = 2; i < n; i++) {
int temp = a;
a = b;
b = temp + b;
}
return b;
}
//迭代算法计算最大的斐波那契数
public static int Max_fibonacciIterative() {
long maxFib = 0;
int index = 0;
long a = 0;
long b = 1;
while (a <= 2147483647L) { // 对于int类型
// while (a <= 9223372036854775807L) { // 对于long类型
maxFib = a;
index++;
long temp = a;
a = b;
b = temp + b;
}
return index;
}
//公式计算
//计算误差最小的数,误差为1
public static int calculateFibonacci_min() {
double sqrt5 = Math.sqrt(5);
double phi = (1 + sqrt5) / 2;
double error = 1.0;
for (int n = 1; ; n++) {
double fibonacci = (Math.pow(phi, n) - Math.pow(-phi, -n)) / sqrt5;
double realFibonacci = calculateFibonacci1(n);
if (Math.abs(fibonacci - realFibonacci) > error) {
return n;
// break;
}
}
}
//真实的阿波期数
public static double calculateFibonacci1(int n) {
if (n <= 2) {
return 1;
}
double a = 1, b = 1;
for (int i = 3; i <= n; i++) {
double c = a + b;
a = b;
b = c;
}
return b;
}
//公式计算 O(1)
public static double calculateFibonacci(int n) {
double sqrt5 = Math.sqrt(5);
double phi = (1 + sqrt5) / 2;
return (Math.pow(phi, n) - Math.pow(-phi, -n)) / sqrt5;
}
//快速矩阵算法 O(logn)
public static int fibonacciMatrixPower(int n){
int x=0,y=1,z=1,p=2;
int temp1=0;int temp2=0;
for(int i=1;i<n-1;i++){
temp1=x;
x=x*0+y*1;
y=temp1*1+y*1;
temp2=z;
z=z*0+p*1;
p=temp2*1+p*1;
}
return y;
}
}
Time.java
package com;
public class Time {
//递归算法
public static long Time_caculate1(int n) {
long startTime = System.currentTimeMillis();
Algorithm.fibonacciRecursive(n);
long endTime = System.currentTimeMillis();
long time= endTime-startTime;
return time;
}
//计算30秒能计算到哪一个
public static int fbnq_dg_time(){
long startTime=System.currentTimeMillis();
int i=1;
long endTime=0;
while(endTime<=startTime+30*1000){
endTime=System.currentTimeMillis();
i++;
Algorithm.fibonacciRecursive(i);
}
return i;
}
//循环算法
public static long Time_caculate2(int n) {
long startTime = System.currentTimeMillis();
Algorithm.fibonacciIterative(n);
long endTime = System.currentTimeMillis();
long time= endTime-startTime;
return time;
}
//计算30秒能计算到哪一个
public static int fbnq_dg_time2(){
long startTime=System.currentTimeMillis();
int i=1;
long endTime=0;
while(endTime<startTime+30*1000){
endTime=System.currentTimeMillis();
i++;
Algorithm.fibonacciIterative(i);
}
return i;
}
//
public static long Time_caculate3(int n) {
long startTime = System.currentTimeMillis();
Algorithm.calculateFibonacci(n);
long endTime = System.currentTimeMillis();
long time= endTime-startTime;
return time;
}
//矩阵算法
public static long Time_caculate4(int n) {
long startTime = System.currentTimeMillis();
Algorithm.fibonacciMatrixPower(n);
long endTime = System.currentTimeMillis();
long time= endTime-startTime;
return time;
}
}
UI.java
package com;
import javax.swing.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class UI {
public static void main(String[] args) {
SwingUtilities.invokeLater(() -> createAndShowGUI());
}
private static void createAndShowGUI() {
JFrame frame = new JFrame("UI界面");
frame.setDefaultCloseOperation(JFrame.EXIT_ON_CLOSE);
frame.setSize(300, 200);
frame.setLocation(500, 300);
JMenuBar menuBar = new JMenuBar();
JMenu algorithmMenu = new JMenu("算法选择");
JMenu recursiveItem = new JMenu("递归");
JMenu iterativeItem = new JMenu("迭代");
JMenu dynamicProgrammingItem = new JMenu("公式计算");
JMenu matrixPowerItem = new JMenu("矩阵快速");
JMenuItem caculate1 =new JMenuItem("计算n");
JMenuItem time1 =new JMenuItem("最大n的时间");
JMenuItem max_30 =new JMenuItem("时间30s");
JMenuItem caculate2 =new JMenuItem("计算n");
JMenuItem time2 =new JMenuItem("时间n");
JMenuItem max2 =new JMenuItem("最大n");
JMenuItem max2_30 =new JMenuItem("时间30s");
JMenuItem caculate3 =new JMenuItem("计算n");
JMenuItem time3 =new JMenuItem("时间n");
JMenuItem min =new JMenuItem("误差最小的n");
JMenuItem caculate4 =new JMenuItem("计算n");
JMenuItem time4 =new JMenuItem("时间n");
algorithmMenu.add(recursiveItem);
algorithmMenu.add(iterativeItem);
algorithmMenu.add(dynamicProgrammingItem);
algorithmMenu.add(matrixPowerItem);
recursiveItem.add(caculate1);
recursiveItem.add(time1);
recursiveItem.add(max_30);
iterativeItem.add(caculate2);
iterativeItem.add(time2);
iterativeItem.add(max2);
iterativeItem.add(max2_30);
dynamicProgrammingItem.add(caculate3);
dynamicProgrammingItem.add(time3);
dynamicProgrammingItem.add(min);
matrixPowerItem.add(caculate4);
matrixPowerItem.add(time4);
menuBar.add(algorithmMenu);
frame.setJMenuBar(menuBar);
//监听事件
caculate1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String inputText = JOptionPane.showInputDialog("请输入一个整数:");
int n;
try {
n = Integer.parseInt(inputText)-1;
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(frame, "请输入有效的整数!");
return;
}
int fibonacciNumber = Algorithm.fibonacciRecursive(n);
JOptionPane.showMessageDialog(frame, "第 " + (n+1) + "个斐波那契数是" + fibonacciNumber);
}
});
time1.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String inputText = JOptionPane.showInputDialog("请输入一个整数:");
int n;
try {
n = Integer.parseInt(inputText)-1;
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(frame, "请输入有效的整数!");
return;
}
long fibonacciNumber = Time.Time_caculate1(n);
JOptionPane.showMessageDialog(frame,"计算出第"+ (n+1) +"个斐波那契数花费的时间为:" +fibonacciNumber+ "毫秒");
}
});
max_30.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int fibonacciNumber = Time.fbnq_dg_time();
JOptionPane.showMessageDialog(frame,"30秒计算到的斐波那契数是第" + fibonacciNumber + "个");
}
});
caculate2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String inputText = JOptionPane.showInputDialog("请输入一个整数:");
int n;
try {
n = Integer.parseInt(inputText);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(frame, "请输入有效的整数!");
return;
}
int fibonacciNumber = Algorithm.fibonacciIterative(n);
JOptionPane.showMessageDialog(frame, "第" + n + "个斐波那契数是 " + fibonacciNumber);
}
});
time2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String inputText = JOptionPane.showInputDialog("请输入一个整数:");
int n;
try {
n = Integer.parseInt(inputText);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(frame, "请输入有效的整数!");
return;
}
long fibonacciNumber = Time.Time_caculate2(n);
JOptionPane.showMessageDialog(frame,"计算出第"+ (n) +"个斐波那契数花费的时间为:" + fibonacciNumber+"毫秒");
}
});
max2.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int fibonacciNumber = Algorithm.Max_fibonacciIterative();
JOptionPane.showMessageDialog(frame, "最大的斐波那契数是" + "第" + fibonacciNumber + "个");
}
});
max2_30.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int fibonacciNumber = Time.fbnq_dg_time2();
JOptionPane.showMessageDialog(frame,"30秒计算到的斐波那契数是第" +fibonacciNumber + "个");
}
});
caculate3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String inputText = JOptionPane.showInputDialog("请输入一个整数:");
int n;
try {
n = Integer.parseInt(inputText);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(frame, "请输入有效的整数!");
return;
} // You can take input from the user
int fibonacciNumber = (int) Algorithm.calculateFibonacci(n);
JOptionPane.showMessageDialog(frame, "第 " + n + "个斐波那契数是" + fibonacciNumber);
}
});
time3.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String inputText = JOptionPane.showInputDialog("请输入一个整数:");
int n;
try {
n = Integer.parseInt(inputText);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(frame, "请输入有效的整数!");
return;
}
long fibonacciNumber = Time.Time_caculate3(n);
JOptionPane.showMessageDialog(frame,"计算出第"+ n +"个斐波那契数花费的时间为:" + fibonacciNumber+"毫秒");
}
});
min.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
int fibonacciNumber = Algorithm.calculateFibonacci_min();
JOptionPane.showMessageDialog(frame, "误差最小时的斐波那契数是" + "第" + fibonacciNumber + "个");
}
});
caculate4.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String inputText = JOptionPane.showInputDialog("请输入一个整数:");
int n;
try {
n = Integer.parseInt(inputText);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(frame, "请输入有效的整数!");
return;
} // You can take input from the user
int fibonacciNumber = (int) Algorithm.fibonacciMatrixPower(n);
JOptionPane.showMessageDialog(frame, "第 " + n + "个斐波那契数是" + fibonacciNumber);
}
});
time4.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String inputText = JOptionPane.showInputDialog("请输入一个整数:");
int n;
try {
n = Integer.parseInt(inputText);
} catch (NumberFormatException ex) {
JOptionPane.showMessageDialog(frame, "请输入有效的整数!");
return;
}
long fibonacciNumber = Time.Time_caculate4(n);
JOptionPane.showMessageDialog(frame,"计算出第"+ (n) +"个斐波那契数花费的时间为:" + fibonacciNumber+"毫秒");
}
});
frame.setVisible(true);
}
}
View_input.java
package com;
import javax.swing.*;
import java.awt.*;
import java.awt.event.ActionEvent;
import java.awt.event.ActionListener;
public class View_Input extends JFrame {
private JTextField textField;
private JButton submitButton;
private int inputValue; // 添加一个成员变量来存储输入的值
public View_Input() {
// 设置窗口标题
setTitle("输入界面");
// 设置布局管理器
setLayout(new GridLayout(3, 2));
// 创建标签和文本框
JLabel label = new JLabel("输入内容:");
textField = new JTextField();
add(label);
add(textField);
// 创建提交按钮并添加点击事件监听器
submitButton = new JButton("提交");
add(submitButton);
submitButton.addActionListener(new ActionListener() {
@Override
public void actionPerformed(ActionEvent e) {
String inputText = textField.getText();
try {
inputValue = Integer.parseInt(inputText); // 将解析后的整数值存储在成员变量中
} catch (NumberFormatException ex) {
System.out.println("无法将字符串转换为整数");
}
}
});
// 设置窗口大小和可见性
setSize(300, 150);
setVisible(true);
setLocation(500, 300);
}
public int getInputValue() {
return inputValue; // 提供一个方法来获取存储的整数值
}
//
// public static void main(String[] args) {
// SwingUtilities.invokeLater(() -> new View_Input());
// }
}