一 . 遇到的问题:
我最初通过eclipse软件设计如下方法:
public static double foraverage(int a,int b) {
double c=(double)(a+b)/2;
return c;
}
但在测试过程中发生了如下问题:
public static void main(String[] args) {
double average=foraverage(1000000000, 2000000000);
System.out.println(average);
}
得到结果为:-6.47483648E8
二 . 问题分析:
1 . 主要原因:
虽然写入两个 int 值 a 和 b,但是当执行“a+b” 命令产生的结果可能超过int的边界([-2147483648,2147483647]),造成了精度损失,所以输出了一个负数。
2 . 解决办法:
根据 int 的边界是双边的,所以需要分为两种情况来考虑:
情况1:给出两个数值为同号
如果为同号的两个数,相加可能出现超出边界情况,所以需要对平均数计算方程需进行如下改动:average=min+(max-min)/2 或者 average=max-(max-min)/2。
情况2:给出两个数值为异号
此时,不论两个数组值在[-2147483648,2147483647]范围内取多少,average=(max+min)/2 均不会超越边界。
综上,本题的编程思路如下:
- 判断所求两个数为 同号 还是 异号,使用 异或(^) 进行判断;
- 同号采用 情况1 的公式编程,需要判断两个数的大小;
- 异号采用 情况2 的公式编程;
- 检验测试编写是否正确。
代码如下:
public static double foraverage(int min,int max) {
double average=0;
if((min^max)>0) {
if(min>max) {
min=min^max;
max=max^min;
min=min^max;
}
average=min+(double)(max-min)/2;
}else {
average=(double)(max+min)/2;
}
return average;
}
经检验,程序成功完成任务目标。
三 . 总结与反思:
1 .反思:
在今后的编程过程中,应该仔细思考,不能因为任务简单而掉以轻心。本题看似提问“如何求平均数”,而实际上考察了 int 类型数值的取值范围、如何不使用乘法判断两个数字是否为同号、if 语句的掌握与应用等多方面知识。所以在今后的编程中,越是简单的细节,越要注意题目是否题中有题,话里有话。尽可能考虑所有可能出现的问题与bug,细节决定成败。
2.总结:通过本题,我学到了如下知识:
a.基本数据类型的取值范围
- byte:[-2^7 , 2^7-1]
- short:[-2^15 , 2^15-1]
- int:[-2^31 , 2^31-1]
- long:[-2^63 , 2^63-1]
- float:[2-149 , 2^128-1]
- double:[2^-1074 ,2^1024-1]
b.如何不使用乘法进行同号异号判断:
在有些情况中,使用乘法判断同号异号可能造成数值超出数据类型的取值范围,所以以后统一通过异或的方法判断两个数字是同号还是异号。
例:判断数值a和数值b是否为同号?
方法:
如果 a^b>0,则判断两个数字为同号或者至少一个数字为0
如果a^b<0,则判断两个数字为异号。
c.一些小技巧:
- 进行除法运算时,可以通过位运算,且位运算速度更快。
int a=4;
System.out.println(a>>1);// 等价于“a/2”
- 异或的活用:异或除了可以用于计算是否同号之外,还可以用来进行数值交换,交换方式:
int x=5;int y=6;
x=x^y;
y=y^x;
x=x^y;
System.out.println(x+","+y);// 输出结果为“6,5”