美文网首页
(一)复数运算

(一)复数运算

作者: 石榴楠 | 来源:发表于2018-12-17 17:50 被阅读0次

    工作之余,突然想用java写一套数值计算的算法套件,权当练手。当然要包括后台和前台,先整后台,具体算法部分。前台考虑web端做个类似“计算器”的东东,等有空再说吧。

    算法

    首先第一天,先来个复数运算。这其中的数学原理就先略过了,当然如果有需要,以后再补充。先来一段源码先:

    
    package com.mysite.algorithm.model;
    
    import lombok.Data;
    
    import lombok.ToString;
    
    import java.util.*;
    
    import java.math.*;
    
    @Data
    
    public class Complex {
    
    private Doublereal =0.0;
    
    private Doubleimaginary =0.0;
    
    private Doubleeps =0.0;//默认精度
    
        public Complex(Double r, Double i){
    
    this.real = r;
    
    this.imaginary = i;
    
    }
    
    public Complex(Complex c){
    
    this.real = c.getReal();
    
    this.imaginary = c.getImaginary();
    
    }
    
    
    public Boolean Equals(Object o){
    
    Complex c = (Complex)o;
    
    if(c ==null)return false;
    
    return Math.abs(this.real - c.getReal()) <=this.eps &&
    
    Math.abs(this.imaginary - c.getImaginary()) <=this.eps;
    
    }
    
    public Complex Add(Complex c){
    
    Double r =this.real + c.getReal();
    
    Double i =this.imaginary + c.getImaginary();
    
    return new Complex(r,i);
    
    }
    
    public Complex Subtract(Complex c){
    
    Double r =this.real - c.getReal();
    
    Double i =this.imaginary - c.getImaginary();
    
    return new Complex(r,i);
    
    }
    
    public Complex Multiply(Complex c){
    
    Double r =this.real * c.getReal() -this.imaginary * c.getImaginary();
    
    Double i =this.real * c.getImaginary() +this.imaginary * c.getReal();
    
    return new Complex(r,i);
    
    }
    
    public Complex Devide(Complex c){
    
    Double e,f,x,y;
    
    if(Math.abs(c.getReal()) >= Math.abs(c.getImaginary())){
    
    e = c.getImaginary() / c.getReal();
    
    f= c.getReal() + e * c.getImaginary();
    
    x = (this.real +this.imaginary * e)/f;
    
    y = (this.imaginary -this.real * e)/f;
    
    }else{
    
    e= c.getReal() / c.getImaginary();
    
    f = c.getImaginary()+ e * c.getReal();
    
    x = (this.real * e +this.imaginary)/f;
    
    y = (this.imaginary *e -this.real)/f;
    
    }
    
    return new Complex(x,y);
    
    }
    
    public Double Abs(){
    
    return Math.sqrt(this.real *this.real +this.imaginary *this.imaginary);
    
    }
    
    // 返回共轭复数
    
        public Complex Conjuagte(){
    
    return new Complex(this.real ,0.0 -this.imaginary);
    
    }
    
    // 求复数的N次方根
    
        public List Root(Integer n){
    
    List ret =new ArrayList<>();
    
    if(n <1)return null;
    
    Double q = Math.atan2(this.imaginary,this.real);
    
    Double r = Math.sqrt(this.real*this.real +this.imaginary *this.imaginary);
    
    if(r!=0){
    
    r = (1.0 /n) * Math.log(r);
    
    r = Math.exp(r);
    
    }
    
    for(Integer k =0;k <= n-1; k++){
    
    Double t = (2.0 *k*Math.PI + q)/n;
    
    Complex complex =new Complex(r*Math.cos(t), r* Math.sin(t));
    
    ret.add(complex);
    
    }
    
    return ret;
    
    }
    
    // 计算复数的实幂指数
    
        public Complex Pow(Double p){
    
    Double r,t;
    
    if(this.imaginary ==0 &&this.real ==0)return new Complex(0.0,0.0);
    
    if(this.real ==0){
    
    if(this.imaginary >0){
    
    t = Math.PI /2;
    
    }else {
    
    t = -Math.PI/2;
    
    }
    
    }
    
    else {
    
    if(this.real >0){
    
    t = Math.atan2(this.imaginary,this.real);
    
    }
    
    else{
    
    if(this.imaginary >0){
    
    t = Math.atan2(this.imaginary,this.real) + Math.PI;
    
    }else{
    
    t = Math.atan2(this.imaginary,this.real) - Math.PI;
    
    }
    
    }
    
    }
    
    r = Math.exp(p * Math.log(Math.sqrt(this.real *this.real +this.imaginary *this.imaginary)));
    
    return new Complex(r* Math.cos(p * t), r* Math.sin(p * t));
    
    }
    
    // 计算复数的复幂指数
    
        public Complex Pow(Complex p, Integer n){
    
    Double r,s,u,v;
    
    if(this.real ==0){
    
    if(this.imaginary ==0)return new Complex(0.0,0.0);
    
    s = Math.PI /2 * (Math.abs(this.imaginary)/this.imaginary +4*n);
    
    }else{
    
    s =2 * Math.PI * n + Math.atan2(this.imaginary,this.real);
    
    if(this.real <0){
    
    s =this.imaginary >0 ? s + Math.PI : s - Math.PI;
    
    }
    
    }
    
    r =0.5 * Math.log(this.real *this.real +this.imaginary *this.imaginary);
    
    v = p.getReal() * r + p.getImaginary() * s;
    
    u = Math.exp(p.getReal() * r - p.getImaginary() * s);
    
    return new Complex(u * Math.cos(v), u * Math.sin(v));
    
    }
    
    // 求复数的自然对数
    
        public Complex Log(){
    
    Double p = Math.log(Math.log(Math.sqrt(this.real *this.real +this.imaginary *this.imaginary)));
    
    return new Complex(p, Math.atan2(this.imaginary,this.real));
    
    }
    
    // 求复数的正弦
    
        public Complex Sin(){
    
    Double p[] = sincos();
    
    Double x = p[0], y = p[1];
    
    return new Complex( x * Math.sin(this.real), y * Math.cos(this.real));
    
    }
    
    // 求复数的余弦
    
        public Complex Cos(){
    
    Double p[] = sincos();
    
    Double x = p[0], y = p[1];
    
    return new Complex( x * Math.cos(this.real), -y * Math.sin(this.real));
    
    }
    
    private Double[] sincos(){
    
    Integer i;
    
    Double x,y ,y1,br =0.0, b1 =0.0, b2 =0.0;
    
    //切比雪夫公式的常数系数
    
            Double c[] =new Double[6];
    
    c[0] =1.13031820798597;
    
    c[1] =0.04433684984866;
    
    c[2] =0.00054292631191;
    
    c[3] =0.00000319843646;
    
    c[4] =0.00000001103607;
    
    c[5] =0.00000000002498;
    
    y1 = Math.exp(this.imaginary);
    
    x =0.5 * (y1 +1/y1);
    
    if(Math.abs(this.imaginary) >=1){
    
    y =0.5 * (y1 -1/y1);
    
    }else{
    
    y1 =2 * (2 *this.imaginary *this.imaginary -1);
    
    for(i =5;i >=0;--i){
    
    br = y1 * b1 - b2 - c[i];
    
    if(i !=0){
    
    b2 = b1;
    
    b1 = br;
    
    }
    
    }
    
    y =this.imaginary * (br - b1);
    
    }
    
    Double ret[] =new Double[2];
    
    ret[0] = x;
    
    ret[1] = y;
    
    return  ret;
    
    }
    
    // 计算复数的正切
    
        public Complex Tan(){
    
    return Sin().Devide(Cos());
    
    }
    
    }
    
    

    验证

    包括了基本运算法则加减乘除还有幂,方根等,基本够用了。那么如何验证我们的代码是否正确呢?这个时候可以借助科学计算领域的大神python,同样的算式看看两边计算的结果是否相等就可以了。
    测试代码如下:

     private static void TestComplex(){
            Complex a = new Complex(2.0,4.0);
            Complex b = new Complex(3.0,-5.0);
    
            System.out.println(a.ToString());
            System.out.println("a+b:" + a.Add(b));
            System.out.println("a-b:" + a.Subtract(b));
            System.out.println("a*b:" + a.Multiply(b));
            System.out.println("a/b:" + a.Devide(b));
    
            System.out.println("sin(a):" + a.Sin());
            System.out.println("cos(a):" + a.Cos());
            System.out.println("sqrt(a)" + a.Root(2));
    
        }
    

    运行结果如下:

    a+b:Complex(real=5.0, imaginary=-1.0, eps=0.0)
    a-b:Complex(real=-1.0, imaginary=9.0, eps=0.0)
    a*b:Complex(real=26.0, imaginary=2.0, eps=0.0)
    a/b:Complex(real=-0.4117647058823529, imaginary=0.6470588235294118, eps=0.0)
    sin(a):Complex(real=24.83130584894638, imaginary=-11.356612711218173, eps=0.0)
    cos(a):Complex(real=-11.36423470640106, imaginary=-24.814651485634183, eps=0.0)
    sqrt(a)[Complex(real=1.7989074399478673, imaginary=1.1117859405028423, eps=0.0), Complex(real=-1.7989074399478673, imaginary=-1.111785940502842, eps=0.0)]
    

    用python进行同样的计算,结果如下:

    import cmath
     a = complex(2,4)
     b = 3-5j
     a+b
    (5-1j)
     a-b
    (-1+9j)
     a*b
    (26+2j)
     a/b
    (-0.4117647058823529+0.6470588235294118j)
    cmath.sin(a)
    (24.83130584894638-11.356612711218174j)
     cmath.cos(a)
    (-11.36423470640106-24.814651485634187j)
    cmath.sqrt(a)
    (1.7989074399478673+1.1117859405028423j)
    ···
    可见二者的结果是一致的,我们的算法正确(其他情况请自行验证)。好了,今天就到此为止了。

    相关文章

      网友评论

          本文标题:(一)复数运算

          本文链接:https://www.haomeiwen.com/subject/dvmckqtx.html