精华内容
下载资源
问答
  • 除了重载相应的操作,也需要实现一个类的一些基本的方法(接口),比如构造、析构、拷贝构造等。 可以使用C++标准模板库(STL)里面的vector类,也可以使用你前一次作业实现的动态数组作为你这次所要实

    向量类和矩阵类的操作符重载

    题目要求

    题目描述
    实现一个向量类,一个矩阵类。在这两个类中,分别重载 “+, -, *(数乘,矩阵乘) ” 基本运算以及 “==,!=,-(负号), =(赋值)" 操作符,以实现向量、矩阵的基本运算。
    要求:

    1. 除了重载相应的操作符,也需要实现一个类的一些基本的方法(接口),比如构造、析构、拷贝构造等。
    2. 可以使用C++标准模板库(STL)里面的vector类,也可以使用你前一次作业实现的动态数组作为你这次所要实现的向量类的基础。

    提示:

    • 此次会提供一份测试代码(非线上测试代码)
    • 该测试用例中涉及的Vecto自行设计,逐渐熟悉并掌握类接口设计能力
    • 建议可以先注释掉全部或大部分测试代码,从而以免在一开始因代码仅完成很少部分,产生太多编译错误
    • 仅通过测试代码分析类的职责,开发完成后,放开测试代码
    • 测试不通过,再考虑职责分析是否有误解
    • 建议思考的方式为“我应该为Vector提供什么接口,这些接口应当完成什么功能以满足他们的职责”为出发点,实现后通过测试用例验证
    • 而非“我应该为Vector提供什么接口,以能通过测试代码”为出发点,通不过一句,改一个函数,通过一句,就转移到下一个函数的方式
    • 前者以对象为中心,考虑职责,在思考过程和实现过程中,类独立设计并实现,最终通过交互完成功能,类设计和实现的过程和测试代码的顺序无关,
    • 仅与自身从测试代码中分析并融合出的职责需求有关
    • 后者以过程为中心,考虑功能,思考过程和实现的过程中,类在不断的“测试过程”中运行,以测试代码运行的顺序增加功能

    输入
    注:由于这次作业不需要提交main()函数,因此输入部分不需要过多关注

    第一行n为整数,表示操作的个数
    第二行的是对数组进行相应操作的代码(整数编码)序列,以空格分隔。

    第三行是m 个数据(m操作序列所需的操作数决定)。

    注:由于这次作业不需要提交main()函数,因此输入部分不需要过多关注
    在这里插入图片描述

    思考过程

    • 向量类使用了vector容器
    • 矩阵类使用线性的内存,顺序存放
    • assert()的调用使得调试更加方便

    代码

    /*向量类和矩阵类的重载运算
    * by——keli
    *2020.12.12
    */
    #include<stdio.h>
    #include<assert.h>
    #include<iostream>
    #include<vector>
    #include<string.h>
    using namespace std;
    class Vector
    {
    public:
        //typedef std::vector<double> Data;
        static Vector INVALID_VECTOR;
    
    public:
        //无参数构造函数
        Vector();
    
        //长度和一个数组为参数的构造函数
        Vector(int length, const double data[]);
    
        //参数为长度和一个double数的构造函数
        Vector(int length, const double data);
    
        //析构函数
        ~Vector();   
    public:
        //返回向量元素个数
        int size() const;
    
        //重载[]
        double operator[](int index) const;
    
        //重载+
        Vector operator+(const Vector& temp) const;
    
        //重载-
        Vector operator-(const Vector& temp) const;
        
        //重载*
        Vector operator*(const double a) const;
    
        //重载==
        bool operator==(const Vector& temp) const;
    
        //重载!=
        bool operator!=(const Vector& temp) const;
    
        //重载负号
        Vector operator-() const;
    
        //重载=double
        Vector operator=(const double element);
    
        //重载+double,每个元素都加一个数
        Vector operator+(const double element)const;
    
        //重载-double,每个元素都减一个数
        Vector operator-(const double element);
    private:
        //重载<<
        friend std::ostream& operator<<(std::ostream& os, const Vector& vector);
    private:
        //数据,向量p
        vector<double>p;
    };
    Vector::Vector()
    {
        p.clear();
    }
    Vector::Vector(int length, const double data[])
    {
        //这里的初始化和容器插入不同,必须先把容器归零
        p.clear();
        for (int i = 0; i < length; i++)
        {//把data[]的数据放入vector
            p.push_back(data[i]);
        }
    }
    Vector::Vector(int length, const double data)
    {
        p.clear();
        for (int i = 0; i < length; i++)
        {
            p.push_back(data);
        }//length个数据初始为data
    }
    Vector::~Vector()
    {
        p.clear();//清理内存
    }
    int Vector::size()const
    {
        //vector内置函数size,返回容器元素个数
        return p.size();
    }
    double Vector::operator[](int index)const
    {
        //随机访问容器元素
        return p.at(index);
    }
    Vector Vector::operator+(const Vector& temp)const
    {
        if (p.size() != temp.p.size())//容量不相等时
        {
            return Vector::INVALID_VECTOR;//返回非法向量
        }
        Vector sum;//和向量
        for (int i = 0; i < p.size(); i++)
        {
            sum.p.push_back(p.at(i) + temp.p.at(i));
        }
        return sum;
    }
    Vector Vector::operator-(const Vector& temp)const
    {
        if (p.size() != temp.p.size())//容量不相等时
        {
            return Vector::INVALID_VECTOR;//返回非法向量
        }
        Vector difference;//差向量
        for (int i = 0; i < p.size(); i++)
        {
            difference.p.push_back(p.at(i) - temp.p.at(i));
        }
        return difference;    
    }
    Vector Vector::operator*(const double a)const
    {
        Vector product;//积向量
        for (int i = 0; i < p.size(); i++)
        {
            product.p.push_back(p.at(i)*a);
        }
        return product;
    }
    bool Vector::operator==(const Vector& temp)const
    {
        return (this->p == temp.p);
    }
    bool Vector::operator!=(const Vector& temp)const
    {
        return (!(this->p == temp.p));
    }
    Vector Vector::operator-()const
    {
        Vector opposite;
        for (int i = 0; i < p.size(); i++)
        {
            opposite.p.push_back(p.at(i)*(-1.0));
        }
        return opposite;
    }
    Vector Vector::operator=(const double element)
    {//把值改为3,长度不变
        int _len = p.size();
        p.clear();//容器重置
        p.resize(_len, element);
        return *this;
    }
    Vector Vector::operator+(const double element)const
    {
        Vector dst;
        for (int i = 0; i < p.size(); i++)
        {
            dst.p.push_back(p[i] + element);
        }
        return dst;
    }
    Vector Vector::operator-(const double element)
    {
        Vector dst;
        for (vector<double>::iterator it = p.begin(); it < p.end(); ++it)
        {
            dst.p.push_back(*it - element);
        }
        return dst;
    }
    
    std::ostream& operator<<(std::ostream& os, const Vector& vector)
    {
        for (int i = 0; i < vector.p.size(); i++)
            os << vector.p.at(i) << " ";
        os << std::endl;
        return os;
    }
    
    //把无效向量设置为0向量
    Vector Vector::INVALID_VECTOR(0, 1.0);
    
    /****************下面是矩阵类******************************************/
    class Matrix
    {
    public:
        /// 定义类型便于其他代码使用
        // typedef std::vector<Vector> Data;
        /// 定义非法矩阵,这里用0 * 0矩阵表示,也可在Matrix中添加一个特殊标志位
        static Matrix INVALID_MATRIX;
    
    public:
        // Matrix类构造函数.
        /// 默认构造函数要加,否则vector无法resize
        Matrix();
    
        //用向量初始化矩阵的构造函数
        Matrix(const Vector& rsh);
    
        //初始化行、列的构造函数
        Matrix(int row, int col);
    
        //行列向量,三参数构造函数
        Matrix(int row, int col, const double data[]);
    
        //行列和一个双精度数的构造函数
        Matrix(int row, int col, const double data);
    
        //拷贝构造函数
        Matrix(const Matrix& rsh);
    
        // Matrix类析构函数
        ~Matrix()
        {
            delete[] p;
            row = 0;
            column = 0;
        }
    
        //返回行数
        int rows()const;
    
        //返回列数
        int cols()const;
        
        //矩阵转置
        Matrix trans()const;
    public:
        //重载矩阵的数乘
        Matrix operator*(const double element)const;
    
        //重载[],返回值是指针,本质上为了实现matrix[][]的访问  
        double* operator[](const int row)const;
        
        //重载==
        bool operator==(const Matrix& rsh)const;
    
        //重载!=
        bool operator!=(const Matrix& rsh)const;
    
        //重载+
        Matrix operator+(const Matrix& rsh)const;
    
        //重载-
        Matrix operator-(const Matrix& rsh)const;
    
        //重载相反数运算
        Matrix operator-(void)const;
    
        //重载矩阵乘法
        Matrix operator*(const Matrix& rsh)const;
    
        
    private:  
        // Matrix类私有实现方法
        int row; // 行
        int column;//列
        
        //访问时p[i+j*column]就相当于二维数组里的p[i][j]
        double * p;//一维向量来存储矩阵
    private:
        /// 所有成员变量应设为私有
    
        /// operator<<需加友元声明,否则无法打印
        friend std::ostream& operator<<(std::ostream& out, const Matrix& rsh);
    }; // class Matrix类定义结束.
    Matrix::Matrix()
    {
        p = NULL;
        row = 0;
        column = 0;
    }
    Matrix::Matrix(const Vector& rsh)
    {//向量相当于行数为1的矩阵
        row = 1;
        column = rsh.size();
        p = new double[row*column];
        for (int j = 0; j < row * column; j++)
        {
            p[j] = rsh[j];
        } 
    }
    Matrix::Matrix(int row, int col)
    {
        this->row = row;
        this->column = col;
        p=new double[row * column];
    }
    Matrix::Matrix(int row, int col, const double data[])
    {
        this->row = row;
        this->column = col;
        p = new double[row * column];
        for (int i = 0; i < row*column; i++)
        {
            p[i] = data[i];
        }
    }
    Matrix::Matrix(int row, int col, const double data)
    {
        this->row = row;
        this->column = col;
        p = new double[row * column];
        for (int i = 0; i < row * column; i++)
        {
            p[i] = data;
        }
    }
    Matrix::Matrix(const Matrix& rsh)
    {
        row = rsh.row;
        column = rsh.column;
        p = new double[row * column];
        for (int i = 0; i < row * column; i++)
        {
            p[i] = rsh.p[i];
        }
    }
    int Matrix::rows()const
    {
        return row;
    }
    int Matrix::cols()const
    {
        return column;
    }
    Matrix Matrix::operator*(const double element) const
    {
        Matrix dst(*this);
        for (int i = 0; i < row * column; i++)
            dst.p[i] = p[i] * element;
        return dst;
    }
    double* Matrix::operator[](const int row)const
    {
        return p + row * this->column;
    }
    bool Matrix::operator==(const Matrix& rsh) const
    {
        if (row != rsh.row || column != rsh.column)
            return false;
        for (int i = 0; i < row * column; i++)
        {
            if (rsh.p[i] != p[i])
                return false;
        }
        return true;
    }
    bool Matrix::operator!=(const Matrix& rsh) const
    {
        return !(*this == rsh);
    }
    Matrix Matrix::operator+(const Matrix& rsh) const
    {
        //矩阵行数列数不一样时返回非法矩阵
        if (row != rsh.rows() || column != rsh.cols())
            return INVALID_MATRIX;
        Matrix dst(*this);
        for (int i = 0; i < dst.cols() * dst.rows(); i++)
        {
            dst.p[i] = p[i] + rsh.p[i];
        }
        return dst;
    }
    Matrix Matrix::operator-(const Matrix& rsh) const
    {
        //矩阵行数列数不一样时返回非法矩阵
        if (row != rsh.rows() || column != rsh.cols())
            return INVALID_MATRIX;
        Matrix dst(*this);
        for (int i = 0; i < dst.cols() * dst.rows(); i++)
        {
            dst.p[i] = p[i] - rsh.p[i];
        }
        return dst;
    }
    Matrix Matrix::operator-(void)const
    {
        Matrix dst(*this);
        for (int i = 0; i < dst.cols() * dst.rows(); i++)
        {
            dst.p[i] = -p[i];
        }
        return dst;
    }
    Matrix Matrix::operator*(const Matrix& rsh)const
    {
        if (this->cols() != rsh.rows())//第一个矩阵的列数与第二个矩阵的行数不相等
        {//返回非法矩阵
            return Matrix::INVALID_MATRIX;
        }
        Matrix dst(this->rows(), rsh.cols());
        for (int i = 0; i < row; i++)
        {
            for (int j = 0; j < dst.column; j++)
            {
                double temp = 0;
                for (int k = 0; k <column; k++)
                {
                    temp += (*this)[i][k] * rsh[k][j];
                }
                dst[i][j]= temp;
            }
        }
        return dst;
    }
    Matrix Matrix::trans()const
    {
        Matrix dst(this->cols(), this->rows());
        for (int i = 0; i <rows(); i++)
        {
            for (int j = 0; j <cols(); j++)
            {
                dst[j][i] = (*this)[i][j];
            }
        }
        return dst;
       
    }
    
    
    
    //非法矩阵设置为0
    Matrix Matrix::INVALID_MATRIX(0, 0);
    // 定义Matrix流输出操作
    std::ostream& operator<<(std::ostream& out, const Matrix& rsh)
    {
        out << "输出矩阵" << endl;
        for (int i = 0; i < rsh.row; i++)
        {
            for (int j = 0; j < rsh.column; j++)
            {
                out << rsh.p[j + i * rsh.column] << " ";
            }
            out << endl;
        }
        return out;
    }
    
    
    
    
    
    // 提供的测试代码
    // 该测试用例中涉及的Vector及Matrix自行设计,逐渐熟悉并掌握类接口设计能力
    // 建议可以先注释掉全部或大部分测试代码,从而以免在一开始因代码仅完成很少部分,产生太多编译错误
    // 仅通过测试代码分析类的职责,开发完成后,放开测试代码
    // 测试不通过,在考虑职责分析是否有误解
    // 建议思考的方式为“我应该为Vector和Matrix提供什么接口,这些接口应当完成什么功能以满足他们的职责”为出发点,实现后通过测试用例验证
    // 而非“我应该为Vector和Matrix提供什么接口,以能通过测试代码”为出发点,通不过一句,改一个函数,通过一句,就转移到下一个函数的方式
    // 前者以对象为中心,考虑职责,在思考过程和实现过程中,类独立设计并实现,最终通过交互完成功能,类设计和实现的过程和测试代码的顺序无关,
    // 仅与自身从测试代码中分析并融合出的职责需求有关
    // 后者以过程为中心,考虑功能,思考过程和实现的过程中,类在不断的“测试过程”中运行,以测试代码运行的顺序增加功能
    
    int main(int argc, char *argv[])
    {
        // 通过传递元素素组初始化向量,最终将得到3个元素
        double data1[] = {3.4, 4.4, 6.0};
        Vector v(sizeof(data1) / sizeof(double), data1);  
        // 确保完备的初始化向量
        assert(v.size() == sizeof(data1) / sizeof(double));    
        for (int idx = 0; idx < sizeof(data1) / sizeof(double); ++idx)
        {
            assert(v[idx] == data1[idx]);
        }    
        // v的值应等于自身,且不会不等于自身
        assert(v == v);
        assert(!(v != v));    
        // v + v按元素分别求和的结果,相当于每个元素直接与2相乘
        assert(v + v == v * 2);    
        // v - v按元素分别求和的结果,相当于v加上v的相反数
        assert(v - v == v + (-v));    
        // v = 3的结果使向量的每个元素都变为3,因此等于直接初始化一个只有三个元素,且初始值为3的向量
        assert((v = 3) == Vector(sizeof(data1) / sizeof(double), 3));    
        // v + 3的结果使向量的每个元素都加上3,因此等于直接初始化一个只有三个元素,且初始值为6的向量
        // 而 v - 3则直接初始化一个只有三个元素,且初始值为0的向量
        assert(v + 3 == Vector(sizeof(data1) / sizeof(double), 6));
        assert(v - 3 == Vector(sizeof(data1) / sizeof(double), 0.0));  
        // 另行定义一个有十个元素,且每个元素值为5的向量
        Vector v2(10, 5);
        // 确保其正确初始化
        assert(v2.size() == 10);
        for (int idx = 0; idx < v2.size(); ++idx)
        {
            assert(v2[idx] == 5);
        }    
        // 两个元素个数不相等的向量相加,其结果为【无效向量】
        assert(v + v2 == Vector::INVALID_VECTOR);
         
        //
        // 通过传递元素素组初始化矩阵,3( 行) X 2(列) 矩阵为:
        // 1 1
        // 1 1
        // 1 1
        double data2[] = {1, 1, 1, 1, 1, 1};  
        Matrix m1(3, 2, data2);
      
       
        // m4等于m1乘以标量2,因此按元素分别求乘积,得到3( 行) X 2(列) 矩阵,为:
        // 2 2
        // 2 2
        // 2 2
        Matrix m4 = m1 * 2;
        
        // 确保m1初始化正确,且与标量乘积正确
        assert(m4.rows() == 3);
        assert(m4.cols() == 2);
        for (int r = 0; r < 2; ++r)
        {
            for (int c = 0; c < 2; ++c)
            {
                assert(m4[r][c] == 2);
            }
        }
        
        // 以同样的数组初始化矩阵,但如果行数、列数不同,获得的矩阵也不同
        Matrix m2(6, 1, data2);
        Matrix m3(3, 2, data2);
       
        // 因此m1与m2同样有6个1,但行列不同,因此不相等
        assert(m1 != m2);
        // 只有m3这样的行列相同,元素相同,才应相等
        assert(m1 == m3);
    
        // 同样的结果可以通过直接初始化每个元素为一个相同的数值得到
        assert(m1 == Matrix(3, 2, 1));
       
        // m1相加之后,应得到一个3行2列,元素全为2的矩阵
        assert(m1 + m1 == Matrix(3, 2, 2));
        // 但如果矩阵行列不同,无法直接相加,只能得到非法矩阵
        assert(m1 + m2 == Matrix::INVALID_MATRIX);
    
        // 同样,减法按元素相减,相当于加上相反数
        assert(m1 - m1 == m1 + (-m1));
        // 相反数的结果应正确
        assert(-m1 == Matrix(3, 2, -1));
        
        // 在乘法中,如果矩阵行列不满足条件,只能得到非法矩阵
        assert(m1 * m1 == Matrix::INVALID_MATRIX);
        // 满足乘法条件,m1与其转置矩阵的乘积((3 X 2) X (2 X 3))为3行3列元素为2矩阵
        assert(m1 * m1.trans() == Matrix(3, 3, 2));
        // 满足乘法条件,m1转置矩阵与m1的乘积((2 X 3) X (3 X 2))为2行2列元素为3矩阵
        assert(m1.trans() * m1 == Matrix(2, 2, 3));
        //cout << v;
        cout << m1;
        cout << Matrix(v);
        cout << (Matrix(v) * m1);
        //向量可转化为矩阵与矩阵相乘,同样要满足矩阵乘法条件,由于v相当于1X3矩阵,元素为3,因此结果为1X2矩阵,元素为9
        assert(Matrix(v) * m1 == Matrix(1, 2, 9));
        // 改变顺序后也可通过转置获得另一个乘积,因此结果为2X1矩阵,元素为9,即相当于上面一个结果的转置
        assert(m1.trans() * Matrix(v).trans() == Matrix(2, 1, 9));
        
        return 0;
    }
    

    结果展示

    • 本次实验实际上没有输入和输出
    • 为了展示结果,写了一个show()函数,再最后进行调用
    void show()
    {
        // 通过传递元素素组初始化向量,最终将得到3个元素
        double data1[] = { 3.4, 4.4, 6.0 };
        Vector v(sizeof(data1) / sizeof(double), data1);
        cout << "v";
        cout << v;
        // 另行定义一个有十个元素,且每个元素值为5的向量
        Vector v2(10, 5);
        cout << "v2";
        cout << v2;
        double data2[] = { 1, 1, 1, 1, 1, 1 };
        Matrix m1(3, 2, data2);
        Matrix m4 = m1 * 2;
        Matrix m2(6, 1, data2);
        Matrix m3(3, 2, data2);
        cout << "m1"  << m1;
        cout << "m2" << m2;
        cout << "m3"  << m3;
        cout << "m4"  << m4;
        cout << "m1转置" << m1.trans();
        cout << "Matrix(v) * m1" << Matrix(v) * m1;
    }
    

    调用显示函数,结果为
    在这里插入图片描述

    总结

    • 再次复习了vector容器的基本用法
    • 复习了C++内存的申请和使用
    • 进一步掌握了程序调试方法,assert()函数的使用
    展开全文
  • 5.4.2向量和矩阵构造器 5.4.3结构体构造器 5.4 构造器(构造函数) 构造函数使用函数调用语法,其中函数名称是基本类型关键字或结构名称,以生成在初始化程序或表达式中使用的所需类型的值。 (有关详细信息,请...

    目录

    5.4 构造器(构造函数)

    5.4.1 转换和标量构造器

    5.4.2向量和矩阵构造器

    5.4.3结构体构造器


    5.4 构造器(构造函数)

    构造函数使用函数调用语法,其中函数名称是基本类型关键字或结构名称,以生成在初始化程序或表达式中使用的所需类型的值。 (有关详细信息,请参见第9节“着色语言语法”。)参数用于初始化构造的值。

    构造函数可用于请求数据类型转换从一种标量类型更改为另一种标量类型,或者用较小类型构建较大类型,或将较大类型减少为较小类型。

    没有固定的构造函数原型列表。 构造函数不是内置函数。 从语法上讲,所有词法正确的参数列表都是有效的。 从语义上讲,参数的数量必须足够大并且类型正确才能执行初始化。 不允许将包含数组的未订阅数组和结构作为构造函数的参数。 参数从左到右进行评估。 向构造函数包含这么多参数是错误的,它们不能全部使用。 详细规则如下。 下面实际列出的原型仅仅是示例的一个子集

    5.4.1 转换和标量构造器

    在标量类型之间进行转换,如以下原型所示:

    int (bool)         //将布尔型值转换成整数

    int (float)         //将浮点数值转换成整数

    float (bool)         //将布尔型值转换成浮点数

    float(int)         //将整型值转换成浮点数

    bool(int)         //将整数值转换成布尔型值

    bool(float)         //将浮点数值转换成布尔型值

    当构造器将一个float转换成int时,浮点数的小数部分将被自动舍弃掉.

    intfloat转换成bool时,0和0.0被转换成false,非0值将被转换成true.当构造器将bool值转换成intfloat时,false被转换成0或0.0, true被转换成1或1.0.

    等价构造器,如float(float)也是合法的,但很少使用到.

    如果构造器的参数不是标量,如向量,那么构造器将取其第一个元素.float (vec3)构造器将取vec3中的第一个值.

    5.4.2向量和矩阵构造器

    构造器也可以用来从标量集合,向量,矩阵中创建向量和矩阵.同时可以缩短向量长度.

    如果使用一个单一的标量来初始化向量,那么向量的所有值均使用该值进行初始化.如果使用一个单一的标量来初始化矩阵,那么矩阵的对角线的所有元素均会被初始化为该值,但其他元素将会被初始化为0.0

    如果一个向量通过多个标量,向量或矩阵或这几种的混合来构造,那么向量的元素将按照参数列表的顺序来初始化.构造器将从参数列表中按从左到右的顺序去取参数,如果参数有多个值,那么再依次从这个参数中将值取出.构造矩阵也是类似的.矩阵元素将按照列为主要顺序来构造.构造器将依次从参数列表中取出参数值来构造矩阵的元素.如果参数列表中的值的个数超过矩阵或向量的元素个数的话,将会引起错误.

    如果使用一个矩阵来构造矩阵的话,那么,参数矩阵中的元素值将放置到新矩阵的相应位置.

    如果基本类型(int , float, bool)作为参数传进构造器,但是要构造的元素类型和传进来的数据类型不同,那么将会使用类型转换.

    一些有用的向量构造函数如下:

    vec3(float) // 使用float初始化每个组件
    vec4(ivec4) // 使用组件转换制作vec4
    vec2(float, float) //使用2个浮点数初始化vec2
    ivec3(int, int, int) //用3个整数初始化一个ivec3
    bvec4(int, int, float, float) // 使用4个布尔转换
    vec2(vec3) // 放弃vec3的第三个组成部分
    vec3(vec4) // 放下vec4的第四个组成部分
    vec3(vec2, float) // vec3.x = vec2.x, vec3.y = vec2.y, vec3.z = float
    vec3(float, vec2) // vec3.x = float, vec3.y = vec2.x, vec3.z = vec2.y
    vec4(vec3, float)
    vec4(float, vec3)
    vec4(vec2, vec2)

    栗子:

    vec4 color = vec4(0.0, 1.0, 0.0, 1.0);
    vec4 rgba = vec4(1.0); // 将每个组件设置为1.0
    vec3 rgb = vec3(color); // 舍弃第四个组件

    要初始化矩阵的对角线,并将所有其他元素设置为零:

    mat2(float)
    mat3(float)
    mat4(float)

    通过为mat2,mat3和mat4分别指定向量或所有4,9或16个浮点数来初始化矩阵。 浮点数按列主要顺序分配给元素。

    mat2(vec2, vec2);
    mat3(vec3, vec3, vec3);
    mat4(vec4, vec4, vec4, vec4);
    mat2(float, float,
             float, float);
    mat3(float, float, float,
             float, float, float,
             float, float, float);
    mat4(float, float, float, float,
             float, float, float, float,
             float, float, float, float,
             float, float, float, float);

    只要存在足够的组件来初始化矩阵,就存在各种其他可能性。

    5.4.3结构体构造器

    一旦结构体被定义,并给了一个类型名,那么和其同名的构造器就可以使用了.

    struct light {
            float intensity;
            vec3 position;
    };
    light lightVar = light(3.0, vec3(1.0, 2.0, 3.0));

    传进构造器的参数必须和结构体里面声明的具有相同的顺序和类型.

    结构体构造器可以用于初始化器或者用在表达式中.

     

    版权:https://blog.csdn.net/flycatdeng/article/details/88984459

    展开全文
  • 一、构造器 Vectors() 二、 方法 修饰和类型 方法 说明 static Vector dense(double[] values) 从双精度数组创建密集向量 static Vector dense(double firstValue, double... otherValues) 根据参数值...

    一、构造器

    Vectors() 
    

    二、 方法

    修饰符和类型 方法 说明
    static Vector dense(double[] values) 从双精度数组创建密集向量
    static Vector dense(double firstValue, double... otherValues) 根据参数值创建密集向量
    static Vector dense(double firstValue, scala.collection.Seq<Object> otherValues) 根据参数值创建密集向量
    static Vector fromJson(String json) 将向量的JSON表示形式解析为Vector类型变量
    static Vector fromML(Vector v) 将新的linalg类型转换为spark.mllib类型
    static double norm(Vector vector, double p) 返回参数向量的p范数
    static Vector parse(String s) Vector.toString产生的字符串解析为Vector类型变量
    static Vector sparse(int size, int[] indices, double[] values) 创建一个稀疏向量,提供其索引数组和值数组
    static Vector sparse(int size, Iterable<scala.Tuple2<Integer,Double>> elements) 以Java友好的方式使用无序(索引,值)对创建稀疏向量

    三、密集向量(dense)和稀疏向量(sparse)

    在上述表格中有两种向量类型,分别是密集向量(dense)和稀疏向量(sparse)

    其中密集向量由一个普通的double类型数组组成,稀疏向量由两个平行的数组组成,即:indices和values。其中indices代表着数组中不为0的元素的索引,values为不为零的元素的值。还有一个size表示稀疏矩阵中元素的个数

    举例说明:

    有一个向量如下所示:

    (1.0,0.0,3.0,0.0,5.0)
    

    用密集向量表示为:

    [1.0,0.0,3.0,0.0,5.0]
    

    用稀疏矩阵表示为:

    (5,[0,2,4],[1.0,3.0,5.0])
    

    其中:5说明有5个元素,[0,2,4]说明索引为0,2,4的三个位置的元素不为0,[1.0,3.0,5.0]说明这三个不为0的元素的值为1.0, 3.0, 5.0

    参考资料:

    1. spark官方文档:http://spark.apache.org/docs/latest/api/java/index.html
    2. 稀疏向量和密集向量:https://blog.csdn.net/qq_35314257/article/details/82799393
    3. spark 密集向量和稀疏向量:https://www.cnblogs.com/asker009/p/12157431.html
    展开全文
  • 向量类C# 文档+程序

    2010-05-09 12:21:46
    4、为Vector定义两个构造函数,一个根据指定长度来对向量进行初始化(向量各个元素取默认值0),另一个由指定的数组来构造向量并设置各元素的值。 5、利用操作重载来实现向量加法、减法和乘法。这三种运算均要求两...
  • 除了重载相应的操作,也需要实现一个类的一些基本的方法(接口),比如构造、析构、拷贝构造等。 可以使用C++标准模板库(STL)里面的vector类,也可以使用你前一次作业实现的动态数组作为你这次所要实现的向量类的...

    用vector容器完成向量类的重载

    题目要求

    题目描述
    实现一个向量类,在类中,分别重载 “+, -, *(数乘,矩阵乘) ” 基本运算以及 “==,!=,-(负号), =(赋值)" 操作符,以实现向量基本运算。

    要求:

    1. 除了重载相应的操作符,也需要实现一个类的一些基本的方法(接口),比如构造、析构、拷贝构造等。
    2. 可以使用C++标准模板库(STL)里面的vector类,也可以使用你前一次作业实现的动态数组作为你这次所要实现的向量类的基础。

    提示:

    • 此次会提供一份测试代码(非线上测试代码)
    • 该测试用例中涉及的Vecto自行设计,逐渐熟悉并掌握类接口设计能力
    • 建议可以先注释掉全部或大部分测试代码,从而以免在一开始因代码仅完成很少部分,产生太多编译错误
    • 仅通过测试代码分析类的职责,开发完成后,放开测试代码
    • 测试不通过,再考虑职责分析是否有误解
    • 建议思考的方式为“我应该为Vector提供什么接口,这些接口应当完成什么功能以满足他们的职责”为出发点,实现后通过测试用例验证
    • 而非“我应该为Vector提供什么接口,以能通过测试代码”为出发点,通不过一句,改一个函数,通过一句,就转移到下一个函数的方式
    • 前者以对象为中心,考虑职责,在思考过程和实现过程中,类独立设计并实现,最终通过交互完成功能,类设计和实现的过程和测试代码的顺序无关,
    • 仅与自身从测试代码中分析并融合出的职责需求有关
    • 后者以过程为中心,考虑功能,思考过程和实现的过程中,类在不断的“测试过程”中运行,以测试代码运行的顺序增加功能

    代码为

    /*向量类的重载运算
    * by——keli
    *2020.12.12
    */
    #include<stdio.h>
    #include<assert.h>
    #include<iostream>
    #include<vector>
    #include<string.h>
    using namespace std;
    class Vector
    {
    public:
        //typedef std::vector<double> Data;
        static Vector INVALID_VECTOR;
    
    public:
        //无参数构造函数
        Vector();
    
        //长度和一个数组为参数的构造函数
        Vector(int length, const double data[]);
    
        //参数为长度和一个double数的构造函数
        Vector(int length, const double data);
    
        //析构函数
        ~Vector();   
    public:
        //返回向量元素个数
        int size();
    
        //重载[]
        double operator[](int index);
    
        //重载+
        Vector operator+(const Vector& temp);
    
        //重载-
        Vector operator-(const Vector& temp);
        
        //重载*
        Vector operator*(const double a);
    
        //重载==
        bool operator==(const Vector& temp);
    
        //重载!=
        bool operator!=(const Vector& temp);
    
        //重载负号
        Vector operator-();
    
        //重载=double
        Vector operator=(const double element);
    
        //重载+double,每个元素都加一个数
        Vector operator+(const double element);
    
        //重载-double,每个元素都减一个数
        Vector operator-(const double element);    
    private:
        //重载<<
        friend std::ostream& operator<<(std::ostream& os, const Vector& vector);
    private:
        //数据,向量p
        vector<double>p;
    };
    Vector::Vector()
    {
        p.clear();
    }
    Vector::Vector(int length, const double data[])
    {
        //这里的初始化和容器插入不同,必须先把容器归零
        p.clear();
        for (int i = 0; i < length; i++)
        {//把data[]的数据放入vector
            p.push_back(data[i]);
        }
    }
    Vector::Vector(int length, const double data)
    {
        p.clear();
        for (int i = 0; i < length; i++)
        {
            p.push_back(data);
        }//length个数据初始为data
    }
    Vector::~Vector()
    {
        p.clear();//清理内存
    }
    int Vector::size()
    {
        //vector内置函数size,返回容器元素个数
        return p.size();
    }
    double Vector::operator[](int index)
    {
        //随机访问容器元素
        return p.at(index);
    }
    Vector Vector::operator+(const Vector& temp)
    {
        if (p.size() != temp.p.size())//容量不相等时
        {
            return Vector::INVALID_VECTOR;//返回非法向量
        }
        Vector sum;//和向量
        for (int i = 0; i < p.size(); i++)
        {
            sum.p.push_back(p.at(i) + temp.p.at(i));
        }
        return sum;
    }
    Vector Vector::operator-(const Vector& temp)
    {
        if (p.size() != temp.p.size())//容量不相等时
        {
            return Vector::INVALID_VECTOR;//返回非法向量
        }
        Vector difference;//差向量
        for (int i = 0; i < p.size(); i++)
        {
            difference.p.push_back(p.at(i) - temp.p.at(i));
        }
        return difference;    
    }
    Vector Vector::operator*(const double a)
    {
        Vector product;//积向量
        for (int i = 0; i < p.size(); i++)
        {
            product.p.push_back(p.at(i)*a);
        }
        return product;
    }
    bool Vector::operator==(const Vector& temp)
    {
        return (this->p == temp.p);
    }
    bool Vector::operator!=(const Vector& temp)
    {
        return (!(this->p == temp.p));
    }
    Vector Vector::operator-()
    {
        Vector opposite;
        for (int i = 0; i < p.size(); i++)
        {
            opposite.p.push_back(p.at(i)*(-1.0));
        }
        return opposite;
    }
    Vector Vector::operator=(const double element)
    {//把值改为3,长度不变
        int _len = p.size();
        p.clear();//容器重置
        p.resize(_len, element);
        return *this;
    }
    Vector Vector::operator+(const double element)
    {
        Vector dst;
        for (int i = 0; i < p.size(); i++)
        {
            dst.p.push_back(p[i] + element);
        }
        return dst;
    }
    Vector Vector::operator-(const double element)
    {
        Vector dst;
        for (vector<double>::iterator it = p.begin(); it < p.end(); ++it)
        {
            dst.p.push_back(*it - element);
        }
        return dst;
    }
    
    std::ostream& operator<<(std::ostream& os, const Vector& vector)
    {
        for (int i = 0; i < vector.p.size(); i++)
            os << vector.p.at(i) << " ";
        os << std::endl;
        return os;
    }
    
    //把无效向量设置为0向量
    Vector Vector::INVALID_VECTOR(0, 1.0);
    
    
    int main(int argc, char *argv[])
    {
        // 通过传递元素素组初始化向量,最终将得到3个元素
        double data1[] = {3.4, 4.4, 6.0};
        Vector v(sizeof(data1) / sizeof(double), data1);  
        // 确保完备的初始化向量
        assert(v.size() == sizeof(data1) / sizeof(double));    
        for (int idx = 0; idx < sizeof(data1) / sizeof(double); ++idx)
        {
            assert(v[idx] == data1[idx]);
        }    
        // v的值应等于自身,且不会不等于自身
        assert(v == v);
        assert(!(v != v));    
        // v + v按元素分别求和的结果,相当于每个元素直接与2相乘
        assert(v + v == v * 2);    
        // v - v按元素分别求和的结果,相当于v加上v的相反数
        assert(v - v == v + (-v));    
        // v = 3的结果使向量的每个元素都变为3,因此等于直接初始化一个只有三个元素,且初始值为3的向量
        assert((v = 3) == Vector(sizeof(data1) / sizeof(double), 3));    
        // v + 3的结果使向量的每个元素都加上3,因此等于直接初始化一个只有三个元素,且初始值为6的向量
        // 而 v - 3则直接初始化一个只有三个元素,且初始值为0的向量
        assert(v + 3 == Vector(sizeof(data1) / sizeof(double), 6));
        assert(v - 3 == Vector(sizeof(data1) / sizeof(double), 0.0));  
        // 另行定义一个有十个元素,且每个元素值为5的向量
        Vector v2(10, 5);
        // 确保其正确初始化
        assert(v2.size() == 10);
        for (int idx = 0; idx < v2.size(); ++idx)
        {
            assert(v2[idx] == 5);
        }    
        // 两个元素个数不相等的向量相加,其结果为【无效向量】
        assert(v + v2 == Vector::INVALID_VECTOR);
        
        return 0;
    }
    
    

    结果

    • 实现了向量类的运算重载
    • 代码没有输出,仅仅使用assert()函数验证功能的实现

    总结

    • 学到了vector容器的常见操作
    • 友元法重载操作符<<
    • 重载符号时,不带参数或者参数为void
    展开全文
  • C++小例子——01 向量类myVector

    千次阅读 2020-06-10 10:12:11
    用C++定义了一个向量类myVector,其包含三个成员变量(x,y,z),可通过三个分量来构造,也可通过另一个myVector对象来构造,重载操作+、-、*、/来完成相关运算,重载赋值=,重载输出流来实现输出,定义友元函数dot...
  • (5)为CzVector定义两个构造函数,一个根据指定长度对向量进行初始化(向量各元素取默认值0),另一个由指定的数组来构造向量并设置各元素的值。 (6)利用操作重载来实现向量加法、减法和乘法。这三种运算均...
  • Advanced R之构造子集

    2015-09-11 09:27:00
    构造子集  R构造子集的操作功能强大而且速度快。精通构造子集者可以用简洁的方式表达复杂的操作,很少有其他语言能做到这一点。...3种构造子集操作。 6类子集。 不同对象(比如向量、列表、因子、矩阵、数据...
  • 然后,将预览控制理论的方法应用于慢子系统,通过对误差向量和状态函数取导数,并以误差向量为新状态向量的一部分,构造了增强系统,并提出了跟踪问题。变成了监管问题。 根据预览控制理论,通过集成在增强系统的...
  • 首先就是关于对向量的操作,一般是用结构体储存x,y,这样方便在结构体中重载操作,使得可以十分方便的进行数学中的一些向量操作,下面就附上关于"+,-乘" struct Pt { int x, y; Pt (){}//先声明函数...
  • 该服务器在SyscDrv构造函数中启动,并在SyscDrv析构函数中停止。 SyscDrv用例 支持的用例 单个SyscDrv实例支持多个请求者和处理程序 Testbench矢量源 Testbench配置源 IP客户端/服务器仿真 不支持的用例 待定 ...
  • vector – 一. vector可以模拟动态数组 – 二. vector的元素可以是任意类型T,但必须具备... 拷贝构造函数和重载的赋值操作) 三.必须包含的头文件#include <vector> – 四. vector支持随机存取 ...
  • 算数操作 (1) GLSL操作与优先级操作描述() 用于表达式组合,函数调用,构造 [ ]数组下标,向量或矩阵的选择器 .结构体和向量的成员选择 ++ --前缀或后缀的自增自减操作 + - !一元操作,表示正 负 ...
  • 通过采用某些标识并将所需跟踪的已知未来信息的差异包括到错误系统的状态向量中,该问题变成了常见描述系统的最优控制问题。 基于结果,提出了一种基于描述离散时间系统的最优控制方法的最优预览控制器的设计...
  • 首先,通过将传感器故障项作为辅助状态向量来制定增强描述系统。 然后构造一个离散时间描述状态观察器,以实现原始系统状态和传感器故障的并发重建。 明确提供了拟议的观测器渐近稳定性的充分必要条件。 为了...
  • [matlab] 矩阵操作

    2017-11-20 23:14:00
    构造1´n矩阵(行向量)时,可以将各元素依次放入矩阵构造符[]内,并且以空格或者逗号分隔;构造m´n矩阵时,每行如上处理,并且行与行之间用分号分隔。 2.特殊矩阵构造 在MATLAB中还提供一些函数用来构造特殊矩阵...
  • 5 操作和表达式 5.1 操作 5.2数组下标 5.3函数调用 5.4 构造器(构造函数... 5.4.2向量和矩阵构造器 5.4.3结构体构造器 5.5 向量组件 6 陈述和结构 6.1 函数定义 6.1.1 函数调用惯例 6.2 选...
  • 许多流行的识别方法可以看作是实现标准处理流程:(1)密集局部特征提取,(2)特征编码,(3)编码局部特征的空间汇集构造特征向量描述,以及(4)将得到的描述呈现给分类器。 池化的作用是产生图像区域的全局...
  • 1. 构造函数实现n维向量的初始化构造,这里n可变; 2. 析构函数实现向量动态内存的释放; 3. 拷贝构造函数和移动拷贝构造函数实现向量的拷贝构造; 4. 重载赋值运算符('=')和移动赋值运算符,实现两个向量之间的...
  • 1.基本操作 四则计算: 逻辑运算: ...这个命令的意思是从1出发,步长为0.1增加,直到增加到2,将这些数据构造成行向量 默认上升步长为1 利用ones生成2x3的矩阵,其中元素全为1 利用zeros生成
  • 1、GLSL操作与优先级操作描述()用于表达式组合,函数调用,构造[]数组下标,向量或矩阵的选择器.结构体和向量的成员++ --前缀或后缀的自增自减操作+ - !一元操作 表示正 负 逻辑非* /乘 除操作+ -二院...
  • 着色器基础2.1 着色器与OpenGL2.2 OpenGL的可编程管线2.3 OpenGL着色语言概述2.3.1 使用GLSL构建着色器从这里出发变量的声明变量的作用域变量的初始化构造函数聚合类型访问向量和矩阵中的元素结构体数组2.3.2 存储...
  • 在pytorch的内部,每个Autograd操作实际上包括对张量的两种操作: forward函数:从输入向量计算输出向量 backward函数:是接受输出向量对于某个标量的梯度,然后计算输入向量相对于这个标量的梯度。 在pytorch...

空空如也

空空如也

1 2 3 4 5 6
收藏数 119
精华内容 47
热门标签
关键字:

向量构造符