C++实现伽罗华域生成及四则运算(二)

上一篇文章介绍了用C++实现伽罗华域 G F ( 2 n ) GF(2^n) GF(2n)生成及四则运算,本篇接上,继续探索,扩展了数的次幂、矩阵数乘、方阵次幂、求行列式、求伴随矩阵、逆矩阵的函数。

一、数的次幂

这比较简单,就是不断乘,代码如下:

/*次幂*/
template<uint8_t n>
uint16_t GFM<n>::gfPow(uint16_t a, uint16_t m) {
    if (a == 0) {
        if (m >= 0) return 0;
        else throw TypeException("除0错误");
    } else if (a == 1) return 1;
    uint16_t res = 1;
    if (m == 0) return 1;
    else { //正常乘,m的类型使得其不可能是负值
        for (int16_t i = 0; i < m % (this->N - 1); i++) { //定理a^(N-1)=1
            res = this->multi(res, a);
        }
    }
    // else { //m < 0,倒数
    //     for (int16_t i = 0; i < (0 - m) % (this->N - 1); i++) { // 计算分母
    //         res = this->multi(res, a);
    //     }
    //     res = this->adver(res); //=1/res
    // } //end of if
    return res;
}

当然符号优先级也得改,还有二元运算的封装函数:

/*二元操作符优先级*/
template<uint8_t n>
int8_t GFM<n>::operatorOrder(char opt) {
    if (opt == '#') return 0; //自定义的用于标志运算符栈结束
    if (opt == '+' || opt == '-') return 1; //加减
    if (opt == '*' || opt == '/') return 2; //乘除
    if (opt == '^') return 3; //次幂
    if (opt == '(' || opt == ')') return 4;
    return -1;
}

/*二元运算操作函数*/
template<uint8_t n>
uint16_t GFM<n>::calculate(uint16_t a, uint16_t b, char opt) {
    if (opt == '+' || opt == '-') return a ^ b;
    else if (opt == '*') return this->multi(a,b);
    else if (opt == '/') return this->multi(a, this->adver(b));
    else if (opt == '^') return this->gfPow(a, b);
    else throw TypeException("运算符错误");
    return 0;
}

二、矩阵数乘

/*矩阵数乘*/
template<uint8_t n>
void GFM<n>::matrixNumMulti(uint16_t* res, uint16_t* A, uint16_t r, uint16_t c, uint16_t m) {
    for (uint16_t i = 0; i < r; i++) {
        for (uint16_t j = 0; j < c; j++) {
            res[i*c+j] = this->multi(A[i*c+j],m);
        }
    }
}

三、矩阵转置

/*使矩阵转置,从r行c列变成c行r列*/
template<uint8_t n>
void GFM<n>::matrixT(uint16_t* res, uint16_t* A, uint16_t r, uint16_t c) {
    if (r == 0 || c == 0) throw TypeException("转置矩阵行列错误");
    for (uint16_t i = 0; i < r; i++) {
        for (uint16_t j = 0; j < c; j++) {
            //第i行j列变为第j行第i列
            res[j*r+i] = A[i*c+j];
        }
    }
}

四、方阵次幂

/*方阵次幂,A是r阶,求A^m*/
template<uint8_t n>
void GFM<n>::matrixPow(uint16_t* res, uint16_t* A, uint16_t r, uint16_t m) {
    if (m == 0) throw TypeException("矩阵幂次出错");
    uint16_t* temp = (uint16_t*)malloc(sizeof(uint16_t) * r * r); //建立缓存矩阵
    memcpy(res, A, sizeof(uint16_t) * r * r);
    for (uint16_t i = 1; i < m; i++) {
        memcpy(temp, res, sizeof(uint16_t) * r * r);
        this->matrixMulti(res, temp, r, r, A, r, r);
    }
    free(temp); //释放缓存
}

五、行列式

使用代数余子式法,将除数不断减小以嵌套计算

/*方阵行列式,r是阶数
代数余子式法
*/
template<uint8_t n>
uint16_t GFM<n>::delta(uint16_t* A, uint16_t r) {
    if (r == 0) throw TypeException("矩阵阶数出错");
    if (r == 1) return A[0];
    if (r == 2) return this->multi(A[0],A[3]) ^ this->multi(A[1],A[2]);
    // 按第0行展开代数余子式
    uint16_t* B = (uint16_t*)malloc(sizeof(uint16_t) * (r-1) * (r-1));
    uint16_t res = 0;
    for (uint16_t omit = 0; omit < r; omit++) { //指定列号,求指定列的代数余子式
        for (uint16_t i = 1, k = 0; i < r; i++) { //从第1行开始读取,写入B[k]
            for (uint16_t j = 0; j < r; j++) { //逐列读取
                if (j == omit) continue; //跳过指定的列
                B[k++] = A[i*r+j];
            }
        }
        res ^= this->multi(A[omit],delta(B, r-1)); //按A的第0行代数余子式展开 
    }
    free(B); //释放内存
    return res;
}

六、伴随矩阵

/*求方阵A的伴随矩阵,r是阶数*/
template<uint8_t n>
void GFM<n>::matrixAsterisk(uint16_t* res, uint16_t* A, uint16_t r) {
    if (r <= 1) throw TypeException("没有伴随矩阵");
    uint16_t* temp = (uint16_t*)malloc(sizeof(uint16_t) * r * r);
    uint16_t* B = (uint16_t*)malloc(sizeof(uint16_t) * (r-1) * (r-1));
    for (uint16_t omit_r = 0; omit_r < r; omit_r++) { //指定行号,求指定行的代数余子式
        for (uint16_t omit_c = 0; omit_c < r; omit_c++) { //指定列号,求指定位置的代数余子式
            //开始写入子方阵
            for (uint16_t i = 0, k = 0; i < r; i++) { //从第0行开始读取,写入B[k]
                if (i == omit_r) continue; //省略本行
                for (uint16_t j = 0; j < r; j++) { //逐列读取
                    if (j == omit_c) continue; //省略本列
                    B[k++] = A[i*r+j];
                }
            }
            //求对应余子矩阵行列式的值
            temp[omit_r*r+omit_c] = this->delta(B, r-1);
// cout << "temp[omit_r*r+omit_c]=" << temp[omit_r*r+omit_c] << endl;
        }
    } //end of for
    free(B); //释放内存
    this->matrixT(res, temp, r, r); //求转置矩阵
    free(temp); //释放内存
}

七、逆矩阵

/*求方阵的逆矩阵,r是阶数*/
template<uint8_t n>
void GFM<n>::matrixAdver(uint16_t* res, uint16_t* A, uint16_t r) {
    uint16_t del = this->delta(A, r);
cout << "|A|=" << del << " 1/|A|=" << this->adver(del) << endl; 
    if (del == 0) throw TypeException("无逆矩阵,因为行列式为0");
    this->matrixAsterisk(res, A, r);
    this->matrixNumMulti(res, res, r, r, this->adver(del)); //A^-1 = A*/|A|
}

八、测试用例

int main(int argc, char*argvs[]) {
    //测试矩阵数乘
    // GFM<8> gf8;
    // uint16_t f[16] = {1,0,0,0, 0,1,0,0, 0,0,1,0, 0,0,0,1};
    // gf8.matrixNumMulti(f, f, 4, 4, 0xe2);
    // for (int i = 0; i < 4; i++) {
    //     for (int j = 0; j < 4; j++){
    //         cout << hex << f[i*4+j] << " ";
    //     }
    //     cout << endl;
    // }

    //测试矩阵次幂
    // GFM<8> gf8;
    // uint16_t a[16] = {2,3,1,1,1,2,3,1,1,1,2,3,3,1,1,2};
    // uint16_t res[16];
    // gf8.matrixPow(res, a, 4, 4);
    // for (int i = 0; i < 4; i++) {
    //     for (int j = 0; j < 4; j++){
    //         cout << hex << res[i*4+j] << " ";
    //     }
    //     cout << endl;
    // }

     //测试方阵行列式
    // GFM<8> gf8;
    // uint16_t a[9] = {2,3,1, 1,2,3, 3,1,2};
    // cout << gf8.delta(a, 3) << endl;
    // uint16_t b[16] = {0x7,0x8,0x9,0xa,0xa,0x7,0x8,0x9,0x9,0xa,0x7,0x8,0x8,0x9,0xa,0x7};
    // cout << gf8.delta(b, 4) << endl;
    // uint16_t c[16] = {0xe,0xb,0xd,0x9, 0xb,0xd,0x9,0xe, 0xd,0x9,0xe,0xb, 0x9,0xe,0xb,0xd};
    // cout << gf8.delta(c, 4) << endl;
    // uint16_t d[25] = {0x5,0x0,0x3,0x2,0x4, 0x4,0x5,0x0,0x3,0x2, 0x2,0x4,0x5,0x0,0x3, 0x3,0x2,0x4,0x5,0x0, 0x0,0x3,0x2,0x4,0x5};
    // cout << gf8.delta(d, 5) << endl;

    //测试矩阵转置
    // GFM<8> gf8;
    // uint16_t a[16] = {2,3,1,1, 1,2,3,1, 1,1,2,3, 3,1,1,2};
    // uint16_t res[16];
    // cout << "原矩阵:" << endl;
    // for (int i = 0; i < 2; i++) {
    //     for (int j = 0; j < 8; j++){
    //         cout << hex << a[i*8+j] << " ";
    //     }
    //     cout << endl;
    // }
    // cout << "转置矩阵:" << endl;
    // gf8.matrixT(res, a, 2, 8);
    // for (int i = 0; i < 8; i++) {
    //     for (int j = 0; j < 2; j++){
    //         cout << hex << res[i*2+j] << " ";
    //     }
    //     cout << endl;
    // }

    //测试伴随矩阵及逆矩阵
    GFM<8> gf8;
    // gf8.toString();
    uint16_t a[16] = {2,4,1,1, 1,2,3,1, 1,1,2,3, 3,1,1,2};
    uint16_t res[16];
    gf8.matrixAsterisk(res, a, 4);
    cout << "伴随矩阵:" << endl;
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++){
            cout << hex << res[i*4+j] << " ";
        }
        cout << endl;
    }
    cout << "逆矩阵:" << endl;
    gf8.matrixAdver(res, a, 4);
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++){
            cout << hex << res[i*4+j] << " ";
        }
        cout << endl;
    }
    cout << "验证:" << endl;
    uint16_t q[16];
    memcpy(q, res, sizeof(uint16_t)*16);
    gf8.matrixMulti(res, q, 4, 4, a, 4, 4);
    for (int i = 0; i < 4; i++) {
        for (int j = 0; j < 4; j++){
            cout << hex << setw(2) << res[i*4+j] << " ";
        }
        cout << endl;
    }


    //命令行计算器实现部分
    // GFM<8> gf8;
    string s;
    while(true) {
        cout << "请输入表达式:" << flush;
        getline(cin,s);
        try {
            cout << hex << gf8.calc(s.c_str()) << endl;
        } catch (TypeException e) { //自定义异常
            cout << e.what() << endl;
        } catch (std::invalid_argument e) { //stoi异常
            cout << e.what() << endl;
        }
    }
    return 0;
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值