函数在计算机中的原理
代码运行的基础
代码都是加载到内存中去执行的,函数的代码也是一样的。内存的大小是有限的,所以需要考虑代码的加载数量和处理生成的数
据量,这些与性能优化有关。
函数的运行环境是堆栈,堆中数据需要入栈进行操作,最终出栈回到堆堆栈用于动态内存的分配和释放。
程序员们通常会把复杂问题分解为若干个较小的容易问题,但是这样代码就会变得冗长并且不易对之后的修改进行操作,而函数
解决了这些问题:
- 降低了代码冗余,复用函数即可
- 降低代码量,适当差分,以便优化
- 将函数模块化
函数的意义
函数主要解决的是那些 重复的 具有 独立功能 的代码段
将这些具有独立功能的代码再次封装就是函数
函数的定义
- 访问权限:函数的使用范围(内部和外部)
- public
- protected
- 默认
- private
- 函数类型:具体的使用场景和场合
- static 静态函数
- 默认不写 成员函数
- abstract 抽象函数
- native 本地函数
- synchronized 同步函数
- 函数名:程序员自定义的名称
- 参数列表:参数列表由若干个参数类型,参数名...组成,主要用于接收外界传递给函数的一些数据
- 函数体:就是那些具有独立功能的代码块
- return:仅仅表示结束当前函数,如果有返回值,则函数结束前将返回值
- 返回值:指的是这一具有独立功能的代码块的计算结果,畜产递给外界,配合return使用
- 返回值类型:就是返回值的类型要和定义的函数类型相同
实际参数:简称实参,主函数在调用函数的时候要给函数传递数据这个数据就是实际参数.
形式参数:简称形参,在定义函数的时候定义的参数名称
参数传递的实质:实参将常量的地址传给形参
局部变量:在函数中创建的变量,作用于当前函数内,形式参数一定是局部变量
函数栈的运行
利用%得到最右边的数字,再用 / 得到去除去掉最右边数字之后的数字
不知道循环次数,用while循环求解
import java.util.Scanner;
public class Home04_01{
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.print("请输入一个整数:");
long number=input.nextLong();
//调用
int sum=sumDigits(number);//通过函数名调用
System.out.println("各位数之和为:"+sum);
}
//定义函数
public static int sumDigits(long number){
int sum=0;
while(true){
sum= (int) (sum + number % 10);
number=number/10;
if(number%10==0){
break;
}
}
return sum;//有参数有返回值,返回值类型和要返回的数据类型相同
}
}
函数的运行时基于栈内存的----栈是一个先进后出的容器
函数的重载
对于同一个类,如果这个类里面有两个或者多个重名的方法,但是方法的参数个数、类型、顺序至少有一个不一样,这时候就构成方法重载。
public class Test03{
public static void main(String[] args) {
int a=1;
int b=2;
int c= add(a, b);
double d=1.1;
double e=2.2;
double f=add(d,e);
System.out.println(c);
System.out.println(f);
}
public static int add(int a,int b){
return a+b;
}
public static double add(double a,double b){
return a+b;
}
}
函数自动识别参数的类型来调用函数,这就是函数的重载,但是函数是重名的
注意:要看清楚的类型,不然会输出错误,因为这样就无法识别到底该使用哪一个参数,会造成二义性。
函数的递归调用
函数自己调用自己就是递归
递归函数就是自己调用自己,一直在栈中操作,如果递归层次过深的话,会导致栈溢出问题的出现。递归就是函数在进栈,进栈次数多了就占内存,无法避免,在某些问题上,递归的代码比迭代少,某些问题迭代是无法解决的
递归是分治法的一种实现方式,分治法主要解决将大问题拆分成若干小的问题进行求解,最终将每个问题的解进行合并,其实分治法就是一种暴力破解法(穷举),也是搜索最佳答案的算法。
递归----->先递,后归
- 前进段---->将问题从大到小
- 结束段---->问题无法再继续化小,则处理当前问题
- 返回段---->将小问题处理完毕后向上返回,(有些问题是不需要返回的)
求1~100的累加问题
public class Test03{
public static void main(String[] args) {
int n=100;
/*
* 计算1+2+3+1+...+99+100
↓递 f(100)=f(99)+100 return 1+2+2+...+99+100
* f(99)=f(98)+99 return 1+2+3+...+98+99
...
f(2)=f(1)+2 retuen 1+2 f(1)=1
return 1 ↑归
*/
f(n);
System.out.println(f(n));
}
public static int f(int n){
if(n==1){
return 1;
}
return f(n-1)+n;
}
}
因为数据不停的进栈最后依次出栈,这样就十分占内存
没有捷径唯有手熟尔
题型练习
编写一个判断是回文的方法再编写一个判断的方法,再通过调用的方式在判断的函数中调用是回文的方法
关键是函数的再次调用问题
import java.util.Scanner;
class Home04_02{
public static void main(String[] args){
Scanner scanner=new Scanner(System.in);
System.out.print("请输入一个数字:");
int num = scanner.nextInt();
if (isPalindrome(num)) {
System.out.println(num + " 是回文!");
}else{
System.out.println(num + " 不是回文!");
}
}
public static int reverse(int num){
int sum=0;
while(num!=0){
sum=sum*10+num%10;
num=num/10;
}
return sum;
}
public static boolean isPalindrome(int num) {
int m=reverse(num);
if(m==num){
return true;
}else{
return false;
}
}
}
这个题直接构造一个打印数字图形的方法在主函数中直接调用就可以了
import java.util.Scanner;
public class Home04_03{
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.print("请输入一个整数:");
int n=input.nextInt();
displayPattern(n);
}
public static void displayPattern(int n){
for(int i=1;i<=n;i++){
for(int k=1;k<=n-i;k++){
System.out.print(" ");
}
for(int j=i;j>=1;j--){
System.out.print(j+" ");
}
System.out.println();
}
}
}
在主函数中输入密码
构造函数判断密码是否有效
调用判断八个以上字符串函数判断
调用判断是否都包含字符和数字函数判断
调用构造至少两个数字的函数判断
import java.util.Scanner;
public class Test04_04 {
public static void main(String[] args) {
Scanner input = new Scanner(System.in);
System.out.println("请输入密码,如果成功则显示成功,否则显示失败!:");
String string = input.nextLine(); //输入的密码
isValidPassword(string);
}
public static void isValidPassword(String string){ //判断密码是否有效
if(isThanEightCharacter(string) && isOnlyCharAndNum(string) &&
isThanTwoDigit(string)){
System.out.println("密码有效!"); //密码输入正确
}else{
System.out.println("密码无效"); //密码输入错误
}
}
public static boolean isThanEightCharacter(String string){ //判断是否少于8个字符
if(string.length() < 8){
return false;
}else{
return true;
}
}
public static boolean isOnlyCharAndNum(String string){ //判断只能包含字母和数字
for(int i=0; i<string.length(); i++){
if(!Character.isLetter(string.charAt(i)) && //字符串中的i对应字符判断是否是字母
!Character.isDigit(string.charAt(i))){ //字符串中的i对应字符判断是否是数字
return false;
}else{
return true;
}
}
return false;
}
public static boolean isThanTwoDigit(String string){ //判断至少有两个数字
int count = 0; //判断是数字的计数器
for(int i=0; i<string.length(); i++){
if(Character.isDigit(string.charAt(i))){
count++;
}
}
if(count>2){
return true;
}else{
return false;
}
}
}
直接构造方法利用条件使用for循环计算公式
主函数调用输出
import java.util.Scanner;
public class Home04_05{
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.println("请输入一个数字:");
double number=input.nextDouble();
double d=sqrt(number);
System.out.println(d);
}
public static double sqrt(double number) {
double nextGuess;
double lastGuess;
for (double i = number / 2; i >= 1; i = i - 0.0001) {
lastGuess = i;
nextGuess = (lastGuess + (number / lastGuess)) / 2;
if(lastGuess-nextGuess<=0.0001){
return nextGuess;
}
}
return 1;
}
}
主函数利用while循环限制范围,定义次数,调用其他函数即可
构造方法判断即是回文也是素数,调用判断函数
构造判断是回文数字的函数
构造判断是素数的函数
public class Home04_06 {
public static void main(String[] args) {
int count=0;//回文数字个数
int num=2;
while(true){
if(isHuiwenSushu(num)){
count++;
System.out.print(num+" ");
if(count%10==0){
System.out.println();
}
}
if(count==100){
break;
}
num++;
}
}
public static boolean isHuiwenSushu(int num){
return isHuiwen(num)&&isSushu(num);
}
public static boolean isHuiwen(int num){
return reverse(num)==num;
}
public static int reverse (int num){
int sum=0;
while(true){
sum=sum*10+num%10;
num=num/10;
if(num==0){
return sum;
}
}
}
public static boolean isSushu(int num){
for(int i=2;i<=num/2;i++){
if(num%i==0){
return false;
}
}
return true;
}
}
主函数调用函数判断是否是反转素数
构造判断反转素数函数
构造回文功能的函数
构造素数功能的函数
构造反转功能的函数
class Demo04_07{
public static void main(String[] args){
int count=0;
int num=2;
while(true){
if(isFanZhuanSuShu(num)){
count++;
System.out.print(num+" ");
if(count%10==0){
System.out.println();
}
}
if(count==100){
return; //结束当前函数
}
num++;
}
}
public static boolean isFanZhuanSuShu(int num){
return isSuShu(num)&&isSuShu(reverse(num))&&!isHuiWen(num);
}
//回文功能
public static boolean isHuiWen(int num){
return reverse(num)==num;
}
//素数功能
public static boolean isSuShu(int num){
for(int i=2;i<=num/2;i++){
if(num%i==0){
return false;
}
}
return true;
}
//反转功能
public static int reverse(int num){
int sum=0;
while(true){
sum=sum*10+num%10;
num/=10;
if(num==0){
return sum;
}
}
}
}
创建输入函数
import java.util.Scanner;
public class Test04_09{
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.print("请输入一个字符串:");
String s = input.nextLine();
char[] chars=s.toCharArray();
for(int j=0;j<chars.length;j++){
System.out.print(chars[chars.length-1-j]);
}
}
}
for循环逐个判断是否在大写的范围
import java.util.Scanner;
public class Test04_10{
public static void main(String[] args) {
Scanner input=new Scanner(System.in);
System.out.print("请输入一个字符串:");
String s = input.nextLine();
int upCount = 0;
for(int i = 0; i < s.length(); i++){
char c = s.charAt(i);
if(c >= 'A' && c <= 'Z') {
upCount++;
}
}
System.out.println("大写之母个数:" + upCount);
}
}
主函数构造输入方法,调用构造函数
import java.util.Scanner;
public class Test04_11 {
public static void main(String[] args) {
System.out.print("请输入两个字符串:");
Scanner input=new Scanner(System.in);
String s1=input.nextLine();
String s2=input.nextLine();
String s3=prefix(s1, s2);
System.out.print(s3);
}
public static String prefix(String s1, String s2) {
int a = s1.length();
int b = s2.length();
int c;
if (a>=b) {
c=b;
}
else{
c=a;
}
char[] k=new char[c];
for (int i = 0; i < c; i++) {
if (s1.charAt(i)==s2.charAt(i)) {
k[i]=s1.charAt(i);
}
if (s1.charAt(i)!=s2.charAt(i)){
break;
}
}
String str = String.valueOf(k);
return str;
}
}