分数的比较。不会有精度的丢失的情况。
一般数学上在比较2个分数大小的时候,有2种方法:
(1)一般是先通分,再比较分子。
但是,通分时需要2个分数的分母直接相乘(或是通分为最小公倍数),但是,有可能溢出整数的范围,所以这种方法不靠谱。
(2)直接分别求出值(可能是浮点数),再直接比较。
但是,将分子分母使用除法/得出商,有时候又恐怕商精度不够。
某些情况下,2个分数本身不相等,但直接求浮点值后,由于浮点数的精度范围有限,浮点数的数值是相等的。
这里的最好的方法是:使用compare方法。思想是:辗转交换方法(我自起的名字)!
例如比较compare(5/18,3/11)=compare(11/3,18/5)=compare(2/3,3/5)=compare(5/3,3/2)=compare(2/3,1/2)=compare(2/1,3/2)=1
/**
* 分数比较。
*
*/
public class FenShuBijiao {
public static void main(String[] args) {
//使用compare方法
System.out.println(compare(1,3,2,3));// 1/3 < 2/3 :-1
System.out.println(compare(1,3,-2,3));// 1/3 > -2/3 :1
System.out.println(compare(3,11,5,18));// 3/11 < 5/18 :-1
System.out.println(compare(11,3,18,5));// 11/3 > 18/5 :1
int bigNum = (-1 >>> 1) - 50;
System.out.println("bigNum="+bigNum);
System.out.println(compare(bigNum-1,bigNum , bigNum , bigNum+1));// (bigNum-1)/bigNum < bigNum/(bigNum+1):-1
//使用除法/,比较符(精度丢失的情况)
System.out.println(0.12345678901234567890 == 0.12345678901234567890000000000001);//true
System.out.println(0.12345678901234567890 > 0.12345678901234567890000000000001);//false
System.out.println(0.12345678901234567890 < 0.12345678901234567890000000000001);//false
}
/**
* 输入2个分数,比较大小。0表示等于关系,1表示大于关系,-1表示小于关系。<br>
*
* 一般数学上在比较2个分数大小的时候,一般是先通分,再比较。<br>
* 例如:比较a/b,c/d大小,则可以通分,比较ad/bd,bc/bd的大小,转化为比较ad和bc的大小。<br>
*
* 但是,ad和bc,有可能溢出整数的范围,所以这种方法不靠谱。必须使用另外一种方法:<br>
* 比较(5/18,3/11)=(11/3,18/5)=(2/3,3/5)=(5/3,3/2)=(2/3,1/2)=(2/1,3/2)=1 <br>
*
* 如果将分子分母使用除法/得出商,有时候又恐怕商精度不够,2个数不相等,但在精度范围内,数值相等也是存在的。
*/
public static int compare(int fenzi1,int fenmu1,int fenzi2,int fenmu2){
//确定2个数的正负符号,1表示正数,0表示负数
int fuhao1 = ~(fenzi1 ^ fenmu1)>>>31;
int fuhao2 = ~(fenzi2 ^ fenmu2)>>>31;
//如果符号不同,则可以直接知道比较结果
if(fuhao1==0 && fuhao2 ==1){
return -1;
}
if(fuhao1==1 && fuhao2 ==0){
return 1;
}
//如果符号相同且都为负
if(fuhao1==0 && fuhao2 ==0){
return compare(Math.abs(fenzi2), Math.abs(fenmu2), Math.abs(fenzi1), Math.abs(fenmu1));
}
//如果符号相同且都为正
//关于分子和分母的关系,共有9种情况
if(fenzi1 == fenmu1 && fenzi2 == fenmu2){
return 0;
}else if(fenzi1 == fenmu1 && fenzi2 > fenmu2){
return -1;
}else if(fenzi1 == fenmu1 && fenzi2 < fenmu2){
return 1;
}else if(fenzi1 > fenmu1 && fenzi2 == fenmu2){
return 1;
}else if(fenzi1 > fenmu1 && fenzi2 > fenmu2){
//分子都大于分母,则求出商和余数
int shang1 = fenzi1/fenmu1;
int yushu1 = fenzi1%fenmu1;
int shang2 = fenzi2/fenmu2;
int yushu2 = fenzi2%fenmu2;
if(shang1 == shang2){//如果商相等,再比价。例如(11/3,18/5)=(2/3,3/5)
return compare(yushu1, fenmu1, yushu2, fenmu2);
}else if(shang1 > shang2){
return 1;
}else{//(shang1 < shang2)
return -1;
}
}else if(fenzi1 > fenmu1 && fenzi2 < fenmu2){
return 1;
}else if(fenzi1 < fenmu1 && fenzi2 == fenmu2){
return -1;
}else if(fenzi1 < fenmu1 && fenzi2 > fenmu2){
return -1;
}else{//(fenzi1 < fenmu1 && fenzi2 < fenmu2)
//分子都小于分母,则分子分母反转,再比较。例如(5/18,3/11)=(11/3,18/5)
return compare(fenmu2, fenzi2, fenmu1, fenzi1);
}
}
}
效果:
-1
1
-1
1
bigNum=2147483597
-1
true
false
false