• 计算分段采样区间中的平均值,标准差,中位数,积分值等的类


    SampleFits.java

    package org.eso.fits;
    
    import java.util.Arrays;
    
    
    public class SampleFits {
    	/*本类完成的功能:对输入的的初始样本lamda, flux,根据整个采样区间的边界值如[3900 9000]以及采样间隔50进行分段,
    	 * 在例子中,lambda和flux的长度应该从小到大有序而且一致,并且lambda的区间范围应该包括边界值[3900 9000];
    	对于每段,可以计算每段flux对应的平均值,标准差,中位数,积分值等方法。*/
    	//错误定义
    	private final int ERROR_NOTFOUND = 0;
    	private final int ERROR_BOUND = 1;
    	private final int ERROR_LENGTH = 2;
    	private final int ERROR_SAMPLESIZE = 3;
    	
    	//类成员变量
    	private double sampleSize;//采样间隔
    	private double sampleLowArea;//整个采样区间的左边界
    	private double sampleUpArea;//整个采样区间的右边界
    	private double[] lambda; //初始数据X
    	private double[] flux;   //初始数据Y
    
    	//初始化类成员变量
    	public SampleFits(double[] dataX, double[] dataY) {
    		
    		sampleSize = 50;
    		sampleLowArea = 3900;
    		sampleUpArea = 9000;
    		
    		lambda = new double[dataX.length];
    		flux = new double[dataY.length];
    		System.arraycopy(dataX, 0, lambda, 0, dataX.length);
    		System.arraycopy(dataY, 0, flux, 0, dataY.length);		
    		
    		if (ErrorCheck() != ERROR_NOTFOUND) {
    			System.out.println("Please take care of the argvs!");
    		}
    	}
    
    	public SampleFits(int sampleSize, int sampleLowArea, int sampleUpArea, double[] dataX, double[] dataY) {
    		this.sampleSize = sampleSize;
    		this.sampleLowArea = sampleLowArea;
    		this.sampleUpArea = sampleUpArea;
    
    		lambda = new double[dataX.length];
    		flux = new double[dataY.length];
    		System.arraycopy(dataX, 0, lambda, 0, dataX.length);
    		System.arraycopy(dataY, 0, flux, 0, dataY.length);			
    		
    		if (ErrorCheck() != ERROR_NOTFOUND) {
    			System.out.println("Please take care of the argvs!");
    		}
    	}
    
    	//获取相关成员变量的值
    	public double GetSampleSize(){
    		return sampleSize;
    	}
    	
    	public double GetsampleLowArea(){
    		return sampleLowArea;
    	}
    	
    	public double GetsampleUpArea(){
    		return sampleUpArea;
    	}
    	
    	//通过整个采样区间以及采样间隔,计算划分的区间个数
    	public int GetRangNum() {
    		double n = (double) (sampleUpArea - sampleLowArea) / (double) sampleSize;
    		return (int) Math.floor(n);
    	}
    
        //获取整个采样区间中每段的平均值
    	public void GetMeanValue(double[] meanValue) {
    		int rangNum = GetRangNum();
    		int[] pointNums = new int[rangNum];
    		CalcPointNums(pointNums);
    		int start_pos = CalcPos(sampleLowArea);
    
    		for (int i = 0; i < rangNum; i++) {
    			double sum = 0;
    			if (pointNums[i] != 0) {
    				for (int j = 0; j < pointNums[i]; j++) {
    					sum += flux[start_pos++];
    				}
    				meanValue[i] = sum / pointNums[i];
    			} else {
    				meanValue[i] = 0;
    			}
    
    		}
    	}
    
    	//获取整个采样区间中每段的标准差
    	public void GetStdValue(double[] stdValue) {
    		int rangNum = GetRangNum();
    		int[] pointNums = new int[rangNum];
    		CalcPointNums(pointNums);
    		int start_pos = CalcPos(sampleLowArea);
    		double[] meanValue = new double[rangNum];
    		GetMeanValue(meanValue);
    
    		for (int i = 0; i < rangNum; i++) {
    			double sum = 0;
    			if (pointNums[i] != 0) {
    				for (int j = 0; j < pointNums[i]; j++) {
    					sum += Math.pow((flux[start_pos++] - meanValue[i]), 2);
    				}
    				stdValue[i] = (double) Math.sqrt(sum / pointNums[i]);
    			} else {
    				stdValue[i] = 0;
    			}
    		}
    	}
    	
    	//获取整个采样区间中每段的中位数
        public void GetMedianValue(double[] midValue) {
        
    		int rangNum = GetRangNum();
    		int[] pointNums = new int[rangNum];
    		CalcPointNums(pointNums);
    		int start_pos = CalcPos(sampleLowArea);
    		
    		int srcPos = start_pos;
    		for (int i = 0; i < rangNum; i++) {
    			double[] flux_rang = new double[pointNums[i]];
    			System.arraycopy(flux, srcPos, flux_rang, 0, pointNums[i]);
    			midValue[i] = CalcMedian(flux_rang);
    			srcPos += pointNums[i];
    		}
        }
        
        //获取整个采样区间的积分值
        public double GetRangIntergral(double[] area){
        	int left_pos = CalcPos(area[0]);
        	int right_pos = CalcPos(area[1]);
        	int len = right_pos - left_pos;
        	double[] lambda_Rang = new double[len];
        	double[] flux_Rang = new double[len];
        	System.arraycopy(lambda, left_pos, lambda_Rang, 0, len);
        	System.arraycopy(flux, left_pos, flux_Rang, 0, len);
        	return CalcIntergral(lambda_Rang, flux_Rang);
        	
        }
        
        //对于给定的arrX和对应的arrY,计算积分值,在x轴上方为正,下方为负进行累加。每一小段通过梯形(或三角形)的面积计算
    	private double CalcIntergral(double[] arrX, double[] arrY){
    
    		double sum = 0;
    		for (int i = 0; i < arrX.length-1; i++) {
    			if (arrY[i] * arrY[i+1] >= 0) {
    				sum += (arrY[i+1] + arrY[i]) * (arrX[i+1] - arrX[i]) / 2;
    			}
    			else {
    				double k = (arrY[i+1] - arrY[i]) / (arrX[i+1] - arrX[i]);
    				double x_0 = arrX[i] - (arrY[i] / k);
    				sum += (arrY[i] * (x_0 - arrX[i]) / 2);
    				sum += (arrY[i+1] * (arrX[i+1] - x_0) / 2);
    			}
    			
    		}
    		return sum;
    	}
    	
    	//错误检测,主要是边界,x,y的长度是否一致,采样间隔设置是否有问题
    	private int ErrorCheck() {
    		double leftBound = lambda[0];
    		double rightBound = lambda[lambda.length - 1];
    
    		if (sampleLowArea < leftBound || sampleUpArea > rightBound) {
    			System.out.println("The bound is error!");
    			return ERROR_BOUND;
    		}
    		else if (lambda.length != flux.length) {
    			System.out.println("The length of lambda and flux is error!");
    			return ERROR_LENGTH;
    		}
    		else if (0 == sampleSize || GetRangNum() < 1) {
    			System.out.println("sampleSize is too large!");
    			return ERROR_SAMPLESIZE;
    		}
    		return ERROR_NOTFOUND;
    		
    	}
    
    	//计算整个采样区间中每段的点的个数
    	private void CalcPointNums(int[] pointNums) {
    		for (int i = 0; i < pointNums.length; i++) {
    			int startPos = CalcPos(sampleLowArea + i * sampleSize);
    			int endPos = CalcPos(sampleLowArea + (i + 1) * sampleSize);
    			pointNums[i] = endPos - startPos;
    
    		}
    
    	}
    
    	//计算某个x坐标的值val在整个全区间中的位置,这里注意的是位置索引是第一个大于val的值的下标
    	private int CalcPos(double val) {
    		int pos = 0;
    		for (int i = 0; i < lambda.length; i++) {
    			if (val < lambda[i]) {
    				pos = i;
    				break;
    			}
    		}
    		return pos;
    	}
    	
    	//对于数组arrY,求中位数,这里是用先排序的方法求中位数
        private double CalcMedian(double[] arrY) {
        	double[] b = new double[arrY.length];
            System.arraycopy(arrY, 0, b, 0, b.length);
            Arrays.sort(b);
    
            if (arrY.length % 2 == 0) {
                return (b[(b.length / 2) - 1] + b[b.length / 2]) / 2.0;
            } else {
                return b[b.length / 2];
            }
        }
        
    }
    


    Test

      	//-----------------------------Test SampleFits----------------------------
        	double[] xx = {1, 2.1, 3.3, 5.4, 7, 9.4, 10, 12.3, 14, 16.5, 17.3, 20};
        	double[] yy = {3, 3, 4, -4, -5, -5, 6, 6, 7, 7, 8, 8};
        	SampleFits testFits = new SampleFits(4, 2, 18, xx, yy);
        	int num = testFits.GetRangNum();
        	System.out.println("num--"+num);
        	
        	double[] mv = new double[num];
        	testFits.GetMeanValue(mv);
        	double[] std = new double[num];
        	testFits.GetStdValue(std);
        	double[] mid = new double[num];
        	testFits.GetMedianValue(mid); 
        	double[] area = {4, 15};
        	double intergal = testFits.GetRangIntergral(area);
        	
        	for (int i = 0; i < std.length; i++) {
    			System.out.println("mean--"+mv[i]);
    			System.out.println("std--"+std[i]);
    			System.out.println("mid--"+mid[i]);
    			System.out.println("intergal--"+intergal);
    		}
        	//-----------------------------------------------------------------------
        	System.out.println("----end ---");


    Output:

    num--4
    mean--1.0
    std--3.559026084010437
    mid--3.0
    intergal--5.949999999999994
    mean---1.3333333333333333
    std--5.185449728701348
    mid---5.0
    intergal--5.949999999999994
    mean--6.5
    std--0.5
    mid--6.5
    intergal--5.949999999999994
    mean--7.5
    std--0.5
    mid--7.5
    intergal--5.949999999999994
    ----end ---
    



  • 相关阅读:
    jq 判断单选是否选中
    C# Split 分隔符为字符串及空格的处理
    MSSQL中的bit类型
    js 判断textarea 不为空
    [转]C#中out 及 ref 区别
    [转]asp.net中时间差的问题
    [转]C# Array 数组 及 一些操作
    Addr、@运算符与Pointer类型
    关于Pascal语言中的分号
    关于以后的文章
  • 原文地址:https://www.cnblogs.com/dyllove98/p/3122988.html
Copyright © 2020-2023  润新知