1. 程式人生 > >Java練習 SDUT-2728_最佳擬合直線

Java練習 SDUT-2728_最佳擬合直線

最佳擬合直線

Time Limit: 1000 ms Memory Limit: 65536 KiB

Problem Description

在很多情況下,天文觀測得到的資料是一組包含很大數量的序列點圖象,每一點用x值和y值定義。這就可能需要畫一條通過這些點的最佳擬合曲線。

為了避免只對個別資料分析,需要進行最佳曲線擬合。考慮N個數據點,它們的座標是(X1,Y1),(X2,Y2)...,(XN,YN)。假設這些值中的X是嚴格的精確值,Y的值是測量值(含有一些誤差)。


對於一個給定的X,如X1,對應的值Y1與曲線C上對應的Y值將存在一個差值。我們用D1表示這個差值,有時我們也稱這個差值為偏差、誤差或殘差,它可能是正、負或零。類似的,X2...,XN,對應的差值為D2,....,DN。

我們用D12 + D22 + ... + DN2 作為衡量曲線C擬合的“最佳”程度,這個值越小越好,越大則越不好。因此,我們做以下定義:任何一種型別的曲線,它們都有一個共同的特性,當ΣDi2最小時,稱為最佳擬合曲線。注:∑指“取和”計算。 一條曲線具有這一特性時,稱之為“最小二乘擬合”,這樣的曲線稱為“最小二乘曲線”。

本次的計算任務是擬合為一條直線,數學上稱之為“線性迴歸”。“迴歸”一詞看起來有點陌生,因為計算最佳曲線沒什麼好“迴歸”的,最好的術語就是“曲線似合”,在直線情況下就是“線性曲線擬合”。

你的任務是編寫程式用最小二乘法計算出以下線性方程的係數(斜率a以及y軸的截距b):

y = a*x + b (4.1)

a和b可以使用以下公式計算:

式中N是資料點的個數。注意,以上兩式具有相同的分母,∑指逐項加法計算(取和)。∑x指對所有的x值求和,∑y指對所以的y值求和,∑(x^2)指對所有x的平方求和。∑xy指對所有的積xy進行取和計算。應注意,∑xy 與 ∑x*∑y是不相同的(“積的和”與“和的積”是不同的),同樣(∑x)^2與∑(x^2)也是不相同的(“和的平方”與“平方的和”是不相同的)。

Input

n組整數表示xi,yi ,期中|x|<=106,|y|<=106, n < 15

Output

最佳擬合曲線引數a和b,a和b各佔一行,a 和b精確到小數點後3位。

Sample Input

4
1 6
2 5
3 7
4 10

Sample Output

1.400
3.500

import java.util.Scanner;

public class Main {

    public static void main(String[] args) {
        Scanner cin = new Scanner(System.in);
        double x,xx,yy,y,xy,q,w;
        int i,n;
        double []a = new double[20];
        double []b = new double[20];
        n = cin.nextInt();
        for(i=0;i<n;i++)
        {
            a[i] = cin.nextDouble();
            b[i] = cin.nextDouble();
        }
        x = get_sum(a,n);
        y = get_sum(b,n);
        xy = get_sum(a,b,n);
        xx = get_sum(a,a,n);
        yy = get_sum(b,b,n);
        q = (n * xy - x * y) / (n * xx - x*x);
        w = (y * xx - x * xy) / (n * xx - x*x);
        System.out.printf("%.3f\n%.3f\n",q,w);
        cin.close();
    }
    
    static double get_sum(double []x,double []y,int n)
    {
        double sum = 0;
        int i;
        for(i=0;i<n;i++)
            sum += x[i] * y[i];
        return sum;
    }
    static double get_sum(double []x,int n)
    {
        double sum = 0;
        int i;
        for(i=0;i<n;i++)
            sum += x[i];
        return sum;
    }
}