一、今日学习目标
本次学习内容主要围绕 Java 运算符展开,并完成一个简易计算器程序。
学习任务:
-
学习 Java 常见运算符
-
理解算术运算符、赋值运算符、比较运算符、逻辑运算符
-
手写一个支持加、减、乘、除、取余的计算器
-
掌握
switch分支判断 -
掌握
do while输入校验 -
理解
int / int的整数除法问题 -
处理除数为 0 的情况
二、运算符基础
1. 算术运算符
算术运算符主要用于数学计算。
| 运算符 | 含义 | 示例 |
|---|---|---|
+ |
加法 | 10 + 3 |
- |
减法 | 10 - 3 |
* |
乘法 | 10 * 3 |
/ |
除法 | 10 / 3 |
% |
取余 | 10 % 3 |
示例:
int a = 10;
int b = 3;
System.out.println(a + b); // 13
System.out.println(a - b); // 7
System.out.println(a * b); // 30
System.out.println(a / b); // 3
System.out.println(a % b); // 1
注意:
10 / 3
结果是:
3
不是:
3.3333
原因是:10 和 3 都是整数,整数除以整数,结果还是整数,小数部分会被舍掉。
2. 赋值运算符
赋值运算符用于给变量赋值。
最基础的是:
int num = 10;
这里的 = 不是数学里的等于,而是赋值。
意思是:把右边的 10 放进左边的变量 num 里面。
常见赋值运算符:
| 运算符 | 示例 | 等价写法 |
|---|---|---|
= |
num = 10 |
把 10 赋值给 num |
+= |
num += 5 |
num = num + 5 |
-= |
num -= 3 |
num = num - 3 |
*= |
num *= 2 |
num = num * 2 |
/= |
num /= 4 |
num = num / 4 |
%= |
num %= 3 |
num = num % 3 |
示例:
int num = 10;
num += 5; // num = 15
num *= 2; // num = 30
num -= 8; // num = 22
System.out.println(num); // 22
计算过程:
num = 10
num += 5 -> 15
num *= 2 -> 30
num -= 8 -> 22
3. 比较运算符
比较运算符用于比较两个值。
比较运算符的结果只有两个:
true
false
常见比较运算符:
| 运算符 | 含义 |
|---|---|
> |
大于 |
< |
小于 |
>= |
大于等于 |
<= |
小于等于 |
== |
判断是否相等 |
!= |
判断是否不相等 |
示例:
int age = 18;
System.out.println(age >= 18); // true
System.out.println(age < 18); // false
System.out.println(age == 18); // true
System.out.println(age != 18); // false
重点区别:
a = b;
这是赋值。
a == b;
这是判断是否相等。
4. 逻辑运算符
逻辑运算符用于连接多个条件。
| 运算符 | 含义 | 说明 |
|---|---|---|
&& |
并且 | 两边都为 true,结果才是 true |
|| |
或者 | 只要有一边是 true,结果就是 true |
! |
取反 | true 变 false,false 变 true |
示例:
int age = 20;
boolean hasTicket = false;
System.out.println(age >= 18 && hasTicket); // false
System.out.println(age >= 18 || hasTicket); // true
System.out.println(!hasTicket); // true
解释:
age >= 18 && hasTicket
年龄满足,但是没有票,所以结果是 false。
age >= 18 || hasTicket
年龄满足,虽然没有票,但是 || 只要一个条件成立,结果就是 true。
!hasTicket
hasTicket 是 false,取反后就是 true。
三、本次计算器程序学习点
1. 使用 Scanner 接收用户输入
代码:
Scanner sc = new Scanner(System.in);
作用:创建一个键盘输入对象。
接收整数:
int a = sc.nextInt();
接收字符串:
String input = sc.next();
接收字符串中的第一个字符:
char op = input.charAt(0);
2. 为什么运算符用 char 类型?
因为本次计算器只需要接收一个运算符,例如:
+
-
*
/
%
这些都是单个字符,所以可以用:
char op;
但是局部变量在使用前必须初始化,所以写成:
char op = ' ';
这里的 ' ' 表示先给变量一个空字符作为占位。
3. 使用 do while 校验运算符
本次代码中使用了:
do {
// 输入和判断
} while (!isValidOp);
意思是:
先执行一次输入,然后判断输入是否合法。
如果输入不合法,就继续循环。
本次判断规则:
if (op == '+' || op == '-' || op == '*' || op == '/' || op == '%') {
isValidOp = true;
}
意思是:只有输入 + - * / % 中的一个,才算合法。
4. 为什么要判断 input.length() == 1?
用户有可能输入:
++
abc
加号
这些都不是一个字符。
所以要先判断:
if (input.length() == 1) {
op = input.charAt(0);
}
只有用户输入的是一个字符,才继续判断这个字符是不是合法运算符。
5. 使用 switch 根据运算符执行不同计算
本次代码使用:
switch (op) {
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
}
意思是:
根据用户输入的运算符,执行对应的计算逻辑。
例如用户输入 +,就执行加法。
用户输入 *,就执行乘法。
6. 除数不能为 0
除法中,第二个数字不能为 0。
错误示例:
10 / 0
所以代码中要判断:
if (b != 0) {
result = (double) a / b;
} else {
System.out.println("错误:除数不能为0!");
isOk = false;
}
取余 % 也不能对 0 取余,所以也需要判断:
if (b != 0) {
result = a % b;
} else {
System.out.println("错误:除数不能为0!");
isOk = false;
}
四、本次重点坑点总结
1. int / int 会丢小数
本次最重要的坑:
int a = 10;
int b = 4;
double result = a / b;
结果是:
2.0
不是:
2.5
原因:
a / b
会先按照整数除法计算,得到 2,再赋值给 double,所以最后是 2.0。
正确写法:
double result = (double) a / b;
这样会先把 a 转成 double,再参与除法计算,结果就是:
2.5
2. 局部变量使用前必须初始化
错误示例:
char op;
如果后续编译器无法确认 op 一定会被赋值,就可能报错。
本次使用:
char op = ' ';
先给一个空字符占位,避免未初始化问题。
3. default 分支也要处理错误状态
虽然前面已经校验过运算符,正常不会进入 default,但是代码要写严谨。
建议写法:
default:
System.out.println("输入的运算符有误!");
isOk = false;
break;
这样即使出现意外情况,也不会错误输出结果。
4. 用 isOk 控制是否输出结果
本次使用:
boolean isOk = true;
如果计算过程中出现错误,例如除数为 0:
isOk = false;
最后输出结果前判断:
if (isOk) {
System.out.println("计算结果是:" + result);
}
这样可以避免程序在出错后继续输出错误结果。
五、本次程序执行流程
整体流程:
1. 创建 Scanner 输入对象
2. 输入第一个数字 a
3. 输入运算符 op
4. 校验 op 是否为 + - * / % 中的一个
5. 如果不合法,继续重新输入
6. 输入第二个数字 b
7. 输出用户输入的表达式
8. 使用 switch 判断运算符
9. 执行对应的加、减、乘、除、取余
10. 如果是除法或取余,判断 b 是否为 0
11. 如果没有错误,输出计算结果
12. 关闭 Scanner
六、测试用例
1. 加法测试
输入:
10
+
5
预期结果:
计算结果是:15.0
2. 减法测试
输入:
10
-
3
预期结果:
计算结果是:7.0
3. 乘法测试
输入:
10
*
3
预期结果:
计算结果是:30.0
4. 除法测试
输入:
10
/
4
预期结果:
计算结果是:2.5
5. 取余测试
输入:
10
%
3
预期结果:
计算结果是:1.0
6. 除数为 0 测试
输入:
10
/
0
预期结果:
错误:除数不能为0!
计算结束...
不会输出计算结果。
7. 错误运算符测试
输入:
10
++
预期结果:
错误:只能输入一个字符,请重新输入!
七、今日掌握情况
本次已经完成:
-
会使用算术运算符:
+ - * / % -
会使用赋值运算符:
= += -= *= /= %= -
会使用比较运算符:
> < >= <= == != -
会使用逻辑运算符:
&& || ! -
会用
Scanner接收键盘输入 -
会用
do while做输入校验 -
会用
switch根据不同运算符执行不同逻辑 -
会判断除数不能为 0
-
理解了
int / int丢小数的问题 -
会使用
(double)强制类型转换解决整数除法问题
八、后续可升级方向
后续可以继续升级这个计算器:
-
支持小数输入,把
int改为double -
支持连续计算
-
支持输入错误数字时重新输入
-
支持退出程序
-
支持更多运算,例如平方、开方
-
使用方法封装,把每种计算写成单独的方法
九、最终源码
文件名:
CalculatorDemo.java
最终代码:
import java.util.Scanner;
public class CalculatorDemo {
public static void main(String[] args) {
Scanner sc = new Scanner(System.in);
System.out.println("请输入第一个数字:");
int a = sc.nextInt();
// System.out.println("请输入运算符(+ - * /):");
// char op = sc.next().charAt(0);
// 假设只允许输入一个计算符| Java 编译器要求局部变量在使用前必须被初始化,虽然 do-while 循环一定会给 op 赋值,但编译器无法静态分析出这一点
char op=' ';
boolean isValidOp = false;
do {
System.out.println("请输入运算符(+ - * / %):");
String input = sc.next();
if (input.length() == 1) {
op = input.charAt(0);
if (op == '+' || op == '-' || op == '*' || op == '/' || op == '%') {
isValidOp = true;
} else {
System.out.println("错误:运算符只能是 + - * / % 中的一个,请重新输入!");
}
} else {
System.out.println("错误:只能输入一个字符,请重新输入!");
}
} while (!isValidOp);
System.out.println("请输入第二个数字:");
int b = sc.nextInt();
System.out.println("输入的数字是:" + a + " " + op + " " + b);
double result = 0;
boolean isOk = true;
System.out.println("开始计算...");
switch (op) {
case '+':
result = a + b;
break;
case '-':
result = a - b;
break;
case '*':
result = a * b;
break;
case '/':
if (b != 0) {
result = (double) a / b;
} else {
System.out.println("错误:除数不能为0!");
isOk = false;
}
break;
case '%':
if (b != 