Change Dir

          先知cd——熱愛生活是一切藝術(shù)的開始

          統(tǒng)計(jì)

          留言簿(18)

          積分與排名

          “牛”們的博客

          各個(gè)公司技術(shù)

          我的鏈接

          淘寶技術(shù)

          閱讀排行榜

          評(píng)論排行榜

          Commons Math學(xué)習(xí)筆記——分?jǐn)?shù)和復(fù)數(shù)

           

          3.2 分?jǐn)?shù)和復(fù)數(shù)

          看其他篇章到目錄選擇。

          我們講到數(shù)學(xué)的計(jì)算,難免會(huì)遇到分?jǐn)?shù)形式,因?yàn)閷?shí)數(shù)的定義就是可以表示為一個(gè)分?jǐn)?shù)的形式的數(shù),而加入虛數(shù)的復(fù)數(shù)也是偶爾會(huì)遇到的。Commons Math包中的fractioncomplex包就分別提供了方法來表示這兩種數(shù)。

          首先來看一個(gè)接口FieldElement<T>,這個(gè)接口定義了一個(gè)泛型參數(shù),其具體內(nèi)容定義了5組方法,分別是加減乘除運(yùn)算和getField()方法。具體Field<T>是什么,這里就不研究了,因?yàn)槲野l(fā)現(xiàn)暫時(shí)還沒有用到它。呵呵。

          像這樣的無算法和實(shí)現(xiàn)的類,具體就是看示例來觀察它的運(yùn)算行為了。

          正式開始,先看看Fraction類,在fraction子包下的Fraction類繼承了java中的Number類,同時(shí)實(shí)現(xiàn)了接口FieldElement<Fraction>Fraction的構(gòu)造方法有5個(gè),支持給定一個(gè)實(shí)數(shù)來構(gòu)建分?jǐn)?shù),也支持給定分子分母的構(gòu)建方法。具體的見代碼吧,因?yàn)榇a已經(jīng)非常直觀了。

           1/**
           2 * 
           3 */

           4package algorithm.math;
           5
           6import org.apache.commons.math.complex.Complex;
           7import org.apache.commons.math.fraction.Fraction;
           8import org.apache.commons.math.fraction.FractionConversionException;
           9
          10/**
          11 * @author Jia Yu
          12 * @date   2010-11-29
          13 */

          14public class FractionAndComplexTest {
          15
          16    /**
          17     * @param args
          18     */

          19    public static void main(String[] args) {
          20        // TODO Auto-generated method stub
          21        fraction();
          22        System.out.println("------------------------------------------------");
          23        complex();
          24    }

          25
          26    private static void complex() {
          27        // TODO Auto-generated method stub
          28        Complex z = new Complex(3.04.0);
          29        Complex x = new Complex(5.07.0);
          30        
          31        //output directly
          32        System.out.println("complex z = "+z);//ugly
          33        System.out.println("complex z = "+c2s(z));//organized manually
          34        System.out.println("complex x = "+c2s(x));
          35        
          36        //complex abs
          37        System.out.println("abs of z = "+z.abs());
          38        //complex add
          39        System.out.println("z+x = "+c2s(z.add(x)));
          40        //complex substrac
          41        System.out.println("z-x = "+c2s(z.subtract(x)));
          42        //complex multiply
          43        System.out.println("z*x = "+c2s(z.multiply(x)));
          44        //complex sin cos 
          45        System.out.println("sin(z) = "+c2s(z.sin()));
          46        System.out.println("cos(z) = "+c2s(z.cos()));
          47        //complex conjugate  
          48        System.out.println("conjugate of z = "+c2s(z.conjugate()));
          49    }

          50    
          51    public static String c2s(Complex c){
          52        if(c.getImaginary()<0)
          53            return ""+c.getReal()+c.getImaginary()+"i";
          54        return ""+c.getReal()+"+"+c.getImaginary()+"i";
          55    }

          56
          57    private static void fraction() {
          58        // TODO Auto-generated method stub
          59        Fraction frac1 = new Fraction(2,3);
          60        
          61        //output directly
          62        System.out.println("frac1 = "+frac1);
          63        
          64        try {
          65            Fraction frac2 = new Fraction(0.5);
          66            System.out.println("frac2 = "+frac2);
          67            
          68            //fraction doublevalue
          69            System.out.println("frac1's double form is "+frac1.doubleValue());
          70            //fraction add
          71            System.out.println("frac1+frac2 = "+frac1.add(frac2));
          72            //fraction substract
          73            System.out.println("frac1-frac2 = "+frac1.subtract(frac2));
          74            //fraction multiply
          75            System.out.println("frac1*frac2 = "+frac1.multiply(frac2));
          76            //fraction divide
          77            System.out.println("frac1/frac2 = "+frac1.divide(frac2));
          78            //fraction multiplicative inverse
          79            System.out.println("frac1's inverse is "+frac1.reciprocal());
          80            
          81            //fraction reduction
          82            System.out.println("5 / 25 = "+Fraction.getReducedFraction(5,25));
          83        }
           catch (FractionConversionException e) {
          84            // TODO Auto-generated catch block
          85            e.printStackTrace();
          86        }

          87    }

          88
          89}

          90

           

          看了具體用法,不免要探究一下,分?jǐn)?shù)的這些運(yùn)算在Commons Math里是怎么實(shí)現(xiàn)的。跟我們直觀感覺一樣,在Fraction類內(nèi)部定義了分子和分母兩個(gè)int型的成員變量。我忍不住要把構(gòu)造方法的源碼貼上來:

           1private Fraction(double value, double epsilon, int maxDenominator, int maxIterations)
           2        throws FractionConversionException
           3    {
           4        long overflow = Integer.MAX_VALUE;
           5        double r0 = value;
           6        long a0 = (long)Math.floor(r0);
           7        if (a0 > overflow) {
           8            throw new FractionConversionException(value, a0, 1l);
           9        }

          10
          11        // check for (almost) integer arguments, which should not go
          12        // to iterations.
          13        if (Math.abs(a0 - value) < epsilon) {
          14            this.numerator = (int) a0;
          15            this.denominator = 1;
          16            return;
          17        }

          18
          19        long p0 = 1;
          20        long q0 = 0;
          21        long p1 = a0;
          22        long q1 = 1;
          23
          24        long p2 = 0;
          25        long q2 = 1;
          26
          27        int n = 0;
          28        boolean stop = false;
          29        do {
          30            ++n;
          31            double r1 = 1.0 / (r0 - a0);
          32            long a1 = (long)Math.floor(r1);
          33            p2 = (a1 * p1) + p0;
          34            q2 = (a1 * q1) + q0;
          35            if ((p2 > overflow) || (q2 > overflow)) {
          36                throw new FractionConversionException(value, p2, q2);
          37            }

          38            
          39            double convergent = (double)p2 / (double)q2;
          40            if (n < maxIterations && Math.abs(convergent - value) > epsilon && q2 < maxDenominator) {
          41                p0 = p1;
          42                p1 = p2;
          43                q0 = q1;
          44                q1 = q2;
          45                a0 = a1;
          46                r0 = r1;
          47            }
           else {
          48                stop = true;
          49            }

          50        }
           while (!stop);
          51
          52        if (n >= maxIterations) {
          53            throw new FractionConversionException(value, maxIterations);
          54        }

          55        
          56        if (q2 < maxDenominator) {
          57            this.numerator = (int) p2;
          58            this.denominator = (int) q2;
          59        }
           else {
          60            this.numerator = (int) p1;
          61            this.denominator = (int) q1;
          62        }

          63
          64    }

          65

           

          為什么是私有的?因?yàn)檫@是最根本的構(gòu)造方法,其他方法都是調(diào)用了這個(gè)基本方法。具體參數(shù)的解釋:value代表了要轉(zhuǎn)化的double值,epsilon表示了最大誤差范圍,maxDenominator表示支持的最大分母,maxIterations表示最大的漸進(jìn)分?jǐn)?shù)。這個(gè)構(gòu)造方法最后得到了分子和分母的表示(numeratordenominator)。其他的運(yùn)算代碼就不用貼了,因?yàn)楸硎境隽朔謹(jǐn)?shù)的分子分母,其他的運(yùn)算容易實(shí)現(xiàn)(其實(shí)是很有趣的,看如何通分約分,利用gcd算法)。

          分?jǐn)?shù)的大分?jǐn)?shù)表示有BigFraction類,具體的用法可以看源碼。

          下面是復(fù)數(shù)的實(shí)現(xiàn):

          關(guān)于復(fù)數(shù)的概念,Complex類里定義了兩個(gè)double變量分別表示復(fù)數(shù)的實(shí)部real和虛部imaginary。復(fù)數(shù)的運(yùn)算相比分?jǐn)?shù)要簡單一些,直觀上看畢竟是一個(gè)線性組合,所以相對(duì)的加減乘除運(yùn)算不涉及到通分和約分這樣需要GCD才能做到的事情。具體的實(shí)現(xiàn)不多講了,沒有意義,直接上示例代碼。因?yàn)楸容^簡單,所以使用到的同學(xué)們直接用就可以了,需要改進(jìn)的可以參看源碼,其實(shí)complex包下的Complex類的源碼也并不長。呵呵1k行而已。

           

          程序輸出結(jié)果:
          frac1 = 2 / 3
          frac2 = 1 / 2
          frac1's double form is 0.6666666666666666
          frac1+frac2 = 7 / 6
          frac1-frac2 = 1 / 6
          frac1*frac2 = 1 / 3
          frac1/frac2 = 4 / 3
          frac1's inverse is 3 / 2
          5 / 25 = 1 / 5
          ------------------------------------------------
          complex z = org.apache.commons.math.complex.Complex@a8780000
          complex z = 3.0+4.0i
          complex x = 5.0+7.0i
          abs of z = 5.0
          z+x = 8.0+11.0i
          z-x = -2.0-3.0i
          z*x = -13.0+41.0i
          sin(z) = 3.853738037919377-27.016813258003932i
          cos(z) = -27.034945603074224-3.851153334811777i
          conjugate of z = 3.0-4.0i

          相關(guān)資料:

          復(fù)數(shù):http://zh.wikipedia.org/zh-cn/%E5%A4%8D%E6%95%B0_%28%E6%95%B0%E5%AD%A6%29

          Commons math包:http://commons.apache.org/math/index.html

          posted on 2010-12-27 22:00 changedi 閱讀(2248) 評(píng)論(0)  編輯  收藏 所屬分類: 數(shù)學(xué)

          主站蜘蛛池模板: 辽宁省| 浠水县| 永春县| 手机| 祥云县| 五河县| 丹阳市| 卫辉市| 宜丰县| 通化市| 望都县| 台北市| 府谷县| 信丰县| 新巴尔虎左旗| 富民县| 湛江市| 天祝| 日喀则市| 望奎县| 元朗区| 龙陵县| 枣强县| 资讯 | 湾仔区| 康乐县| 漳浦县| 宕昌县| 清河县| 安达市| 勐海县| 潞城市| 北川| 南昌市| 合肥市| 罗源县| 同江市| 定西市| 华池县| 雅安市| 莆田市|