實驗二 插值方法(android)

許佳佳233發表於2016-04-22

實驗一部落格地址:http://blog.csdn.net/double2hao/article/details/51152843


一、實驗內容

分別寫出拉格朗日插值法與牛頓插值法的演算法,編寫程式上機除錯出結果,要求所程式設計序適用於在任何一組插值節點,即能解決這一類問題,而不是某一個問題。

試驗中以下列資料驗證程式的正確性。

已知下列函式表

X   0.56160   0.56280   0.56401   0.56521

Y   0.82741   0.82659   0.82577   0.82495

求X=0.5635時的函式值。


最終效果:(原始碼在文章底部)

  


主要工作:

1、理解拉格朗日插值法和牛頓插值法的公式。


2、由於採用的是fragment,直接複用的實驗一的xml佈局。


3、牛頓插值法的演算法中採用了遞迴,為了提高效率直接在遞迴中判斷是否要加入牛頓插值的結果。


具體演算法就不多說了,主要邏輯寫在TwoFragment中,若對此作業有興趣可以自行拖到底部下載原始碼。


TwoFragment.java

package com.example.double2.numericcalculationtest;

import android.app.Fragment;
import android.os.Bundle;
import android.util.Log;
import android.view.LayoutInflater;
import android.view.View;
import android.view.ViewGroup;
import android.widget.ArrayAdapter;
import android.widget.Button;
import android.widget.EditText;
import android.widget.Spinner;
import android.widget.TextView;
import android.widget.Toast;

import java.text.DecimalFormat;

/**
 * 專案名稱:NumericCalculationTest
 * 建立人:Double2號
 * 建立時間:2016/4/13 21:41
 * 修改備註:
 */
public class TwoFragment extends Fragment {
    private View views;
    private TextView tvTitle;
    private TextView tvGuidance;
    private Button btnInPut;
    private EditText etInput;
    private Button btnClear;
    private TextView tvProgress;
    private TextView tvResult;
    private Spinner spChose;
    private final String[] spinnerChose = {"Lagrange插值", "Newton插值"};

    private String xShow;//用來展示過程
    private String yShow;//用來展示過程
    private int dataSize;
    private Double[][] data;
    private Double myX;
    private int linePosition;//行座標
    private Double resultNewton = 0.0;
    private boolean[] hasAdded; //記錄該均差是否已經計算過,加入過了結構
    private DecimalFormat mDecimalFormat = new DecimalFormat("0.00000000");//保留八位小數


    @Override
    public View onCreateView(LayoutInflater inflater, ViewGroup container, Bundle savedInstanceState) {
        views = inflater.inflate(R.layout.fra_one_and_two, null);
        initView();
        return views;
    }

    private void initView() {
        tvTitle = (TextView) views.findViewById(R.id.tv_title);
        tvGuidance = (TextView) views.findViewById(R.id.tv_one_guidance);
        btnInPut = (Button) views.findViewById(R.id.btn_input);
        etInput = (EditText) views.findViewById(R.id.et_input);
        btnClear = (Button) views.findViewById(R.id.btn_clear);
        tvProgress = (TextView) views.findViewById(R.id.tv_one_progress);
        tvResult = (TextView) views.findViewById(R.id.tv_one_result);
        spChose = (Spinner) views.findViewById(R.id.sp_one_chose);

        tvTitle.setText("插值方法");
        tvGuidance.setText(R.string.input_data_size);
        spChose.setAdapter(new ArrayAdapter<String>(getActivity(),
                android.R.layout.simple_list_item_1, spinnerChose));

        btnInPut.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                caculating();
            }
        });
        btnClear.setOnClickListener(new View.OnClickListener() {
            @Override
            public void onClick(View v) {
                clearData();
            }
        });
    }

    private void clearData() {
        tvGuidance.setText(R.string.input_data_size);
        xShow = "";
        yShow = "";
        tvProgress.setText("");
        tvResult.setText("");
        linePosition = 0;
        dataSize = 0;
        data = null;
        hasAdded = null;
        btnInPut.setClickable(true);
    }

    private void caculating() {
        //獲取到EditText中的String
        //如果為空就提示使用者並且直接返回
        String textInput = etInput.getText().toString();
        etInput.setText("");
        if (textInput.equals("")) {
            Toast.makeText(getActivity(), R.string.not_input_null, Toast.LENGTH_SHORT).show();
            return;
        }

        //Lagrange插值和Newton插值在計算之前的讀取資料過程一樣
        readData(textInput);

    }

    private void readData(String textInput) {
        String textGuidance = tvGuidance.getText().toString();
        //通過提示的TextView的text來判斷進行到哪一步
        if (textGuidance.equals(getString(R.string.input_data_size))) {
            dataSize = Integer.parseInt(textInput);
            data = new Double[2][dataSize];
            xShow = "x分別為:\n";
            yShow = "y分別為:\n";
            tvProgress.setText(xShow + yShow);
            tvGuidance.setText(R.string.input_x);
            linePosition = 0;

        } else if (textGuidance.equals(getString(R.string.input_x))) {
            data[0][linePosition] = Double.parseDouble(textInput);
            Log.d("xujiajia1", data[0][linePosition] + "");
            xShow += data[0][linePosition] + "\n";
            tvProgress.setText(xShow + yShow);
            tvGuidance.setText(R.string.input_y);
        } else if (textGuidance.equals(getString(R.string.input_y))) {
            data[1][linePosition] = Double.parseDouble(textInput);
            yShow += data[1][linePosition] + "\n";
            tvProgress.setText(xShow + yShow);
            linePosition++;

            //倘若還沒有輸入完
            if (linePosition != dataSize) {
                tvGuidance.setText(R.string.input_x);
            } else {
                tvGuidance.setText(R.string.input_my_x);
                yShow += "你需要測的x為:\n";
                tvProgress.setText(xShow + yShow);
            }

        } else if (textGuidance.equals(getString(R.string.input_my_x))) {
            myX = Double.parseDouble(textInput);
            yShow += myX + "\n";
            tvProgress.setText(xShow + yShow);
            tvGuidance.setText(R.string.input_end);

            if (spChose.getSelectedItemPosition() == 0) {
                LagrangeCaculation();
            } else {
                NewtonCaculation();
            }

        }
    }

    private void LagrangeCaculation() {
        Double result = 0.0;
        Double aloneResule;
        for (int i = 0; i < dataSize; i++) {
            aloneResule = data[1][i];
            for (int j = 0; j < dataSize; j++) {
                if (i != j) {
                    aloneResule *= (myX - data[0][j]) / (data[0][i] - data[0][j]);
                }
            }
            result += aloneResule;
        }
        tvResult.setText(mDecimalFormat.format(result) + "");
        btnInPut.setClickable(false);
    }

    private void NewtonCaculation() {
        hasAdded = new boolean[dataSize];
        for (int i = 0; i < dataSize; i++) {
            hasAdded[i] = false;
        }
        int[] dataIndex = new int[dataSize];
        for (int i = 0; i < dataSize; i++)
            dataIndex[i] = i;

        resultNewton = data[1][0];//初始值為
        hasAdded[0] = true;
        meanDeviation(dataIndex);//開始遞迴
        tvResult.setText(mDecimalFormat.format(resultNewton) + "");
        btnInPut.setClickable(false);
    }

    //計算均差的遞迴,並且在每次遞迴的時候判斷是否要加入到結果裡
    private Double meanDeviation(int[] dataIndex) {
        int size = dataIndex.length;
        Double deviation;

        if (size == 1) {
            deviation = data[1][0];
        } else if (size == 2) {
            deviation = (data[1][dataIndex[1]] - data[1][dataIndex[0]]) /
                    (data[0][dataIndex[1]] - data[0][dataIndex[0]]);
        } else {
            //如果大於二就進入遞迴
            int[] dataIndex_one = new int[size - 1];
            int[] dataIndex_two = new int[size - 1];
            for (int i = 0; i < size - 2; i++) {
                dataIndex_one[i] = dataIndex[i];
                dataIndex_two[i] = dataIndex[i];
            }
            dataIndex_one[size - 2] = dataIndex[size - 1];
            dataIndex_two[size - 2] = dataIndex[size - 2];
            deviation = (meanDeviation(dataIndex_one) - meanDeviation(dataIndex_two)) /
                    (data[0][dataIndex[size - 1]] - data[0][dataIndex[size - 2]]);
        }

        //判斷這個值是否要加到newton插值的結果中
        boolean isNeedAdd = true;
        if (dataIndex[0] == 0) {
            for (int i = 0; i < size - 1; i++) {
                if (dataIndex[i] != dataIndex[i + 1] - 1) {
                    isNeedAdd = false;
                    break;
                }
            }
        } else {
            isNeedAdd = false;
        }

        //如果是滿足要求的均差並且沒有新增過,那麼久新增
        if (isNeedAdd && !hasAdded[size - 1]) {
            hasAdded[size - 1] = true;
            double item = deviation;
            for (int j = 0; j < size - 1; j++) {
                Log.d("xujiajia4", size + "  " + data[0][j]);
                item *= (myX - data[0][j]);
                Log.d("xujiajia4", item + "");
            }
            resultNewton += item;
        }
        return deviation;
    }


}

原始碼地址:
http://download.csdn.net/detail/double2hao/9498851

相關文章