`
atell
  • 浏览: 159178 次
  • 性别: Icon_minigender_1
  • 来自: 杭州
文章分类
社区版块
存档分类
最新评论

[C趣味编程]分数的比较compare(不会有精度的丢失的情况)

阅读更多

分数的比较。不会有精度的丢失的情况。

 

一般数学上在比较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

 

分享到:
评论

相关推荐

Global site tag (gtag.js) - Google Analytics