c++矩阵运算

优化了一些算法
#pragma once
#include <iostream>
#include <iomanip>
#include <string>

#define OVERFLOWED 1E-12
class Matrix
{
public:
    Matrix(int m, int n);             //构建一个m*n的全零矩阵
    Matrix(int n);                 //构建一个n*n的单位矩阵
    Matrix(const Matrix &);         //拷贝构造函数,深拷贝
    Matrix(double* items, int m, int n);//根据数组拷贝一个矩阵
    ~Matrix();
    static Matrix FromFile(std::string file);
    int getRowNum() const;                //返回矩阵的行数
    int getColNum() const;                //返回矩阵的列数

    Matrix Trans() const;                //将矩阵转置

    double get(int i, int j) const;            //返回矩阵第i行j列元素
    void set(int i, int j, double val);        //设置矩阵第i行j列元素

    Matrix operator +(const Matrix &m);         //两个矩阵相加
    Matrix operator -(const Matrix &m);         //两个矩阵相减
    Matrix operator *(const Matrix &m);         //两个矩阵相乘
    Matrix operator *(const double f);         //矩阵乘以常数
    Matrix& operator=(const Matrix& m);
    Matrix Inverse();
    
    friend std::ostream& operator <<(std::ostream &os, const Matrix &m);

private:
    double *item;        //指向矩阵首元素
    int rowNum;        //矩阵行数
    int colNum;        //矩阵列数

private:
    //矩阵初等行变换
    //如果j=-1,则对i扩大multiply倍
    //如果j在取值范围内,则将第i行扩大multiply倍加到j行
    void RowSwap(int i, int j, double multiply);
    //交换两行
    void RowSwap(int i, int j);
    void FlowOver();
};
#include "Matrix.h"
#include <vector>
#include <cmath>
#include <fstream>
#include <sstream>

using namespace std;
Matrix::Matrix(int m, int n)
{
    if (m < 0 || n < 0)
    {
        cout << "矩阵大小不能为负\n";
        return;
    }
    rowNum = m;
    colNum = n;
    item = new double[m*n];
    for (int i = 0; i < m*n; i++)
    {
        item[i] = 0;
    }
}

//也可用二维数组初始化
Matrix::Matrix(double* items, int m, int n)
{
    rowNum = m;
    colNum = n;
    item = new double[m*n];
    for (int i = 0; i < colNum*rowNum; i++)
    {
        item[i] = items[i];
    }
}
Matrix::Matrix(int n)
{
    rowNum = colNum = n;
    item = new double[n*n];
    for (int i = 0; i < n; i++)
    {
        for (int j = 0; j < n; j++)
        {
            if (i == j)
                set(i, j, 1.0);
            else
                set(i, j, 0);
        }
    }
}
Matrix::Matrix(const Matrix &M)
{
    colNum = M.colNum;
    rowNum = M.rowNum;
    //这里不能对指针直接赋值,复制对求逆、转置等操作会影响原矩阵
    item = new double[colNum*rowNum];
    for (int i = 0; i < colNum*rowNum; i++)
    {
        item[i] = M.item[i];
    }
}
Matrix& Matrix::operator=(const Matrix & M)
{
    colNum = M.colNum;
    rowNum = M.rowNum;
    if (item != nullptr) delete[] item;
    item = new double[colNum*rowNum];
    for (int i = 0; i < colNum*rowNum; i++)
    {
        item[i] = M.item[i];
    }
    return *this;
}

Matrix Matrix::FromFile(std::string file)
{
    ifstream read(file);
    if (!read.is_open())
    {
        cout << "Matrix::未能打开文件\n";
    }
    int rows = 0;
    string line;
    vector<double> nums;
    while (getline(read, line))
    {
        istringstream record(line);
        double num = 0.0;
        while (record >> num)  nums.push_back(num);
        rows++;
    }
    return Matrix(&(*nums.begin()), rows, nums.size() / rows);
}

Matrix::~Matrix()
{
    delete[] item;
}
double Matrix::get(int i, int j) const
{
    return item[i*colNum + j];
}
void Matrix::set(int i, int j, double value)
{
    item[i*colNum + j] = value;
}
void Matrix::RowSwap(int i, int j, double multiply)
{
    if (j == -1)
    {
        for (int k = 0; k < colNum; k++)
        {
            set(i, k, multiply*get(i, k));
        }
    }
    else
    {
        for (int k = 0; k < colNum; k++)
        {
            set(j, k, multiply*get(i, k) + get(j, k));
        }
    }
}
void Matrix::RowSwap(int i, int j)
{
    Matrix _copy = *this;
    for (int k = 0; k < colNum; k++)
    {
        double swap = _copy.get(j, k);
        set(j, k, _copy.get(i, k));
        set(i, k, swap);
    }
}
Matrix Matrix::Trans() const
{
    Matrix _copy = *this;
    _copy.rowNum = this->colNum;
    _copy.colNum = this->rowNum;
    for (int i = 0; i < _copy.rowNum; i++)
    {
        for (int j = 0; j < _copy.colNum; j++)
        {
            _copy.set(i, j, get(j, i));
        }
    }
    return _copy;
}
int Matrix::getRowNum() const
{
    return rowNum;
}
int Matrix::getColNum() const
{
    return colNum;
}
ostream& operator <<(ostream &os, const Matrix &m)
{
    for (int i = 0; i < m.rowNum; i++)
    {
        for (int j = 0; j < m.colNum; j++)
            os << std::setw(10) << std::fixed << std::setprecision(12) << m.get(i, j) << " ";
        os << "\n";
    }
    os.flush();
    return os;
}
Matrix Matrix::operator +(const Matrix &m)
{
    if (m.colNum != colNum || m.rowNum != rowNum) return *this;
    Matrix _copy = *this;
    for (int i = 0; i < rowNum; i++)
    {
        for (int j = 0; j < colNum; j++)
        {
            _copy.set(i, j, get(i, j) + m.get(i, j));
        }
    }
    return _copy;
}
Matrix Matrix::operator -(const Matrix &m)
{
    if (m.colNum != colNum || m.rowNum != rowNum) return *this;
    Matrix _copy = *this;
    for (int i = 0; i < rowNum; i++)
    {
        for (int j = 0; j < colNum; j++)
        {
            _copy.set(i, j, get(i, j) - m.get(i, j));
        }
    }
    return _copy;
}
Matrix Matrix::operator *(const double f)
{
    Matrix _copy = *this;
    for (int i = 0; i < rowNum; i++)
    {
        for (int j = 0; j < colNum; j++)
        {
            _copy.set(i, j, get(i, j)*f);
        }
    }
    return _copy;
}
Matrix Matrix::operator *(const Matrix &m)
{
    if (colNum != m.rowNum)
    {
        cout << "无法相乘!";
        return *this;
    }
    Matrix _copy(rowNum, m.getColNum());
    for (int i = 0; i < rowNum; i++)
    {
        for (int j = 0; j < m.colNum; j++)
        {
            double sum = 0;
            for (int k = 0; k < m.rowNum; k++)
            {
                sum += get(i, k)*m.get(k, j);
            }
            _copy.set(i, j, sum);
        }
    }
    return _copy;
}
Matrix Matrix::Inverse()
{
    Matrix _copy = *this;
    //变换结果
    Matrix result(colNum);
    if (colNum != rowNum)
    {
        cout << "矩阵不可逆!" << endl;
        return *this;
    }
    for (int i = 0; i < rowNum; i++)
    {
        int MaxRow = i;
        //首先找到第i列的绝对值最大的数,并将该行和第i行互换
        double max = abs(_copy.get(i, i));
        for (int j = i; j < colNum; j++)
        {
            if (abs(_copy.get(j, i))>max)
            {
                max = abs(_copy.get(j, i));
                MaxRow = j;
            }
        }
        //交换j,i两行
        if (MaxRow != i)
        {
            result.RowSwap(i, MaxRow);
            _copy.RowSwap(i, MaxRow);
        }
        //将第i行做初等行变换,将第一个非0元素化为1
        double r = 1.0 / _copy.get(i, i);
        _copy.RowSwap(i, -1, r);
        result.RowSwap(i, -1, r);
        //消元
        for (int j = 0; j < rowNum; j++)
        {
            if (j == i) continue;
            r = -_copy.get(j, i);
            _copy.RowSwap(i, j, r);
            result.RowSwap(i, j, r);
        }
    }
    //result.FlowOver();
    return result;
}
void Matrix::FlowOver()
{
    for (int i = 0; i < rowNum;i++)
    {
        for (int j = 0; j < colNum;j++)
        {
            if (abs(get(i, j)) <= OVERFLOWED) set(i, j, 0);
        }
    }
}

 

 

 

 

posted @ 2016-11-04 18:57  啊王会  阅读(17708)  评论(2编辑  收藏  举报