C语言实现2x2矩阵求逆出错:整数除法导致计算结果异常
2x2矩阵求逆的整数除法问题修复
我要实现用于密码学场景的2x2矩阵求逆功能,现有代码多数情况能正常运行,但输入特定矩阵(比如[[1,10],[3,4]])时计算异常。这个矩阵的行列式是-26,程序计算1/-26输出0.0000,但正确结果应该是−0.038461538。测试代码double test = 1/(-26);同样输出0.0000,推测问题和整数除法有关,求错误修复方法。
原代码如下:
#include <stdio.h> #include <stdlib.h> int main(){ int i, Mtx_P[4], temp; float D, Mtx_I[4]; printf("\nInsert the values in a matrix 2x2: "); // Insert the values for(i=0;i<4;i++) { scanf("%d", &Mtx_P[i]); } printf(" \n"); for(i=0;i<4;i++) // Print the values { printf("%d\t", Mtx_P[i]); if(i == 1) { printf("\n\n"); } } D = (Mtx_P[0] * Mtx_P[3]) - (Mtx_P[1] * Mtx_P[2]); // Find and print the determinant printf("\n\n-------------------------\n\nDeterminant = %f\n", D); float Mtx_Pf[4]; //double Mtx_Pf[4]; I've tried with double to see if worked for(i=0;i<4;i++) // Find the inverse... { Mtx_Pf[i] = Mtx_P[i]; } Mtx_I[0] = Mtx_Pf[0]/D; // ...divind the values by the determinat Mtx_I[1] = Mtx_Pf[1]/D; Mtx_I[2] = Mtx_Pf[2]/D; Mtx_I[3] = Mtx_Pf[3]/D; temp = Mtx_I[0]; // swaping the places of the first number with the lastest one Mtx_I[0] = Mtx_I[3]; Mtx_I[3] = temp; Mtx_I[1]*=-1; // the secondary diagonal get negative Mtx_I[2]*=-1; printf("\n-------------------------\n\nThe invertible Matrix:\n\n "); for(i=0;i<4;i++) // Print the inverse { printf("%f\t", Mtx_I[i]); if(i == 1) { printf("\n\n"); } } double test = 1/(-26); printf("\n\n-------------------------\n(Test: %lf)\n\n", test); // Testing to see if it can't calculate return 0; }
问题根源
C语言中,当两个整数进行除法运算时(比如1和-26都是int类型),会执行整数除法,结果只保留整数部分。1/-26的整数结果是0,再赋值给double变量时就变成了0.0000,这是直接诱因。另外原代码的矩阵求逆步骤顺序错误,也会导致结果偏差。
修复步骤
- 规避整数除法:在除法运算时,确保至少有一个操作数是浮点类型。比如把
1/(-26)改成1.0/(-26),编译器会自动将另一个操作数转换为浮点类型,执行浮点除法。 - 修正求逆顺序:2x2矩阵求逆的正确数学逻辑是:
- 交换主对角线元素(a和d)
- 副对角线元素(b和c)取反
- 最后所有元素除以行列式D
原代码先做除法再交换取反,顺序完全错误。
- 提升精度:密码学场景对精度要求较高,将
float替换为double类型,减少精度损失。
修复后的完整代码
#include <stdio.h> #include <stdlib.h> int main(){ int i, Mtx_P[4]; double D, Mtx_I[4]; // 改用double提升精度 printf("\n请输入2x2矩阵的4个元素:"); for(i=0;i<4;i++) { scanf("%d", &Mtx_P[i]); } printf("\n输入的矩阵:\n"); for(i=0;i<4;i++) { printf("%d\t", Mtx_P[i]); if(i == 1) { printf("\n\n"); } } // 计算行列式时先转浮点,避免大整数溢出 D = (double)Mtx_P[0] * Mtx_P[3] - (double)Mtx_P[1] * Mtx_P[2]; printf("\n\n-------------------------\n\n行列式 = %lf\n", D); // 按照正确顺序计算逆矩阵 Mtx_I[0] = (double)Mtx_P[3] / D; // 主对角线交换:原d/D Mtx_I[1] = -(double)Mtx_P[1] / D; // 副对角线b取反后/D Mtx_I[2] = -(double)Mtx_P[2] / D; // 副对角线c取反后/D Mtx_I[3] = (double)Mtx_P[0] / D; // 主对角线交换:原a/D printf("\n-------------------------\n\n逆矩阵:\n\n"); for(i=0;i<4;i++) { printf("%lf\t", Mtx_I[i]); if(i == 1) { printf("\n\n"); } } // 测试修复后的浮点除法 double test = 1.0/(-26); printf("\n\n-------------------------\n(测试:%lf)\n\n", test); return 0; }
关键修复说明
- 通过
1.0或(double)强制将整数转换为浮点类型,触发浮点除法 - 严格遵循2x2矩阵求逆的数学公式:对于矩阵
[[a,b],[c,d]],逆矩阵为(1/D) * [[d, -b], [-c, a]](D为行列式ad-bc) - 使用
double类型存储计算结果,满足密码学场景的精度需求
内容的提问来源于stack exchange,提问作者Yuri
相关产品推荐
相关产品推荐

