Change Dir

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

          統計

          留言簿(18)

          積分與排名

          “牛”們的博客

          各個公司技術

          我的鏈接

          淘寶技術

          閱讀排行榜

          評論排行榜

          Commons Math學習筆記——分數和復數

           

          3.2 分數和復數

          看其他篇章到目錄選擇。

          我們講到數學的計算,難免會遇到分數形式,因為實數的定義就是可以表示為一個分數的形式的數,而加入虛數的復數也是偶爾會遇到的。Commons Math包中的fractioncomplex包就分別提供了方法來表示這兩種數。

          首先來看一個接口FieldElement<T>,這個接口定義了一個泛型參數,其具體內容定義了5組方法,分別是加減乘除運算和getField()方法。具體Field<T>是什么,這里就不研究了,因為我發現暫時還沒有用到它。呵呵。

          像這樣的無算法和實現的類,具體就是看示例來觀察它的運算行為了。

          正式開始,先看看Fraction類,在fraction子包下的Fraction類繼承了java中的Number類,同時實現了接口FieldElement<Fraction>Fraction的構造方法有5個,支持給定一個實數來構建分數,也支持給定分子分母的構建方法。具體的見代碼吧,因為代碼已經非常直觀了。

           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

           

          看了具體用法,不免要探究一下,分數的這些運算在Commons Math里是怎么實現的。跟我們直觀感覺一樣,在Fraction類內部定義了分子和分母兩個int型的成員變量。我忍不住要把構造方法的源碼貼上來:

           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

           

          為什么是私有的?因為這是最根本的構造方法,其他方法都是調用了這個基本方法。具體參數的解釋:value代表了要轉化的double值,epsilon表示了最大誤差范圍,maxDenominator表示支持的最大分母,maxIterations表示最大的漸進分數。這個構造方法最后得到了分子和分母的表示(numeratordenominator)。其他的運算代碼就不用貼了,因為表示出了分數的分子分母,其他的運算容易實現(其實是很有趣的,看如何通分約分,利用gcd算法)。

          分數的大分數表示有BigFraction類,具體的用法可以看源碼。

          下面是復數的實現:

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

           

          程序輸出結果:
          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

          相關資料:

          復數: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) 評論(0)  編輯  收藏 所屬分類: 數學

          主站蜘蛛池模板: 榆中县| 易门县| 泽州县| 台南县| 奎屯市| 隆回县| 韩城市| 威宁| 都安| 永济市| 太原市| 福贡县| 博罗县| 东阳市| 新乐市| 斗六市| 施甸县| 会昌县| 武清区| 永靖县| 麻城市| 昌黎县| 长宁县| 翼城县| 镇雄县| 凌源市| 汤阴县| 吴堡县| 黑山县| 安徽省| 麟游县| 大理市| 西丰县| 福州市| 桑日县| 浪卡子县| 渭南市| 左权县| 普兰店市| 城市| 黔西县|