用于高斯乔丹消去的 C++ 程序返回一个非常小的值但不为 0
C++ program for Gauss Jordan elimination returning a very small value but not 0
我编写了一个使用高斯乔丹消去法求解线性方程组的程序。该程序运行正常,但在某些情况下,不是给出答案 0,而是 returns 一个非常小的值。
#include<iostream>
#include<iomanip>
#include<cassert>
#define N 10
using namespace std;
//printing out the array
void print(float x[][N], int n){
for(int i=0;i<n;i++){
for(int j=0;j<=n;j++)
cout << setprecision(5) << setw(15) <<x[i][j];
cout << endl;
}
cout << endl;
}
//to normalise the leading entries to 1
void normalize(float x[][N], int n, int i, int j){
float fac = x[i][j];
for(int k=0;k<=n;k++)
x[i][k] /= fac;
}
//check if the leading entry is a zero
bool chk_zero(float x[][N], int n, int i){
int j, k, c{0};
if(x[i][i]==0){
for(j=i;j<n-1;j++){
c=1;
while(x[j+c][i]==0 && i+c<n){
c++;
if(i+c==n-1)
assert(i+c==n-1 && "Equation has no solution");
return false;
}
for(k=0;k<=n;k++){
swap(x[i][k], x[i+c][k]);
}
return true;
}
}
return true;
}
//Gauss Jordan elimination method
void GaussJordan(float x[][N], int n){
int i, j, k, c;
float rat;
for(i=0;i<n;i++){
//not taking the zero in pivot column case
chk_zero(x, n, i);
normalize(x, n, i, i);
for(j=0;j<n;j++){
if (i != j){
float fac{x[j][i]};
for(k=0;k<=n;k++)
x[j][k] = x[j][k]-fac*x[i][k];
}
}
}
}
int main(){
float arr[][N] = { {0, 5, 1, 2},
{2, 11, 5, 3},
{1, 0, 0, 0} };
int n = sizeof(arr)/sizeof(arr[0]);
print(arr, n);
GaussJordan(arr, n);
cout << n << endl;
print(arr, n);
return 0;
}
我得到的输出是:
1 0 0 2.3842e-08
0 1 0 0.5
-0 -0 1 -0.5
我应该得到的输出是:
1 0 0 0
0 1 0 0.5
-0 -0 1 -0.5
值 2.3842e-08 应为零。是因为C++中浮点数的精度吗?
如果是这样,我应该怎么做才能在不丢失数据的情况下将如此低的值舍入为 0?
另外,为什么是“-0”而不是 0。
The value 2.3842e-08 should be a zero. Is it because of the precision of the floating point in C++ ?
是的,是的。
If so, what should I do in order to round such low values to 0 without loss of data ?
您可以使用 epsilon
值来决定浮点值是否被视为 0:
const float epsilon = 0.000001; // Depends on the use case of your application
if (std::abs(some_float) < epsilon) {
// Treat some_float as 0
}
但是,这种方法有一些缺点。阅读 here 了解更多。
Also, why is there a "-0" instead of a 0.
这是因为浮点数的表示方式。大多数 C++ 编译器使用 IEEE 754 标准来实现浮点运算。
补充几点(与问题无关):
- 您应该避免使用
using namespace std
,因为它会污染全局命名空间。特别是对于大型代码库。
- 使用
std::array<>
而不是原始数组,因为它们更安全。
The value 2.3842e-08 should be a zero.
Is it because of the precision of the floating point in C++ ?
没有。根据 IEEE-754 标准,它是二进制数字系统中浮点数表示的一个特征。它是在硬件中实现的,几乎所有语言都在使用它。所有的浮点计算都带有错误,因此您应该为 FPU 设置正确的舍入模式。有关详细信息,请参阅 。
我编写了一个使用高斯乔丹消去法求解线性方程组的程序。该程序运行正常,但在某些情况下,不是给出答案 0,而是 returns 一个非常小的值。
#include<iostream>
#include<iomanip>
#include<cassert>
#define N 10
using namespace std;
//printing out the array
void print(float x[][N], int n){
for(int i=0;i<n;i++){
for(int j=0;j<=n;j++)
cout << setprecision(5) << setw(15) <<x[i][j];
cout << endl;
}
cout << endl;
}
//to normalise the leading entries to 1
void normalize(float x[][N], int n, int i, int j){
float fac = x[i][j];
for(int k=0;k<=n;k++)
x[i][k] /= fac;
}
//check if the leading entry is a zero
bool chk_zero(float x[][N], int n, int i){
int j, k, c{0};
if(x[i][i]==0){
for(j=i;j<n-1;j++){
c=1;
while(x[j+c][i]==0 && i+c<n){
c++;
if(i+c==n-1)
assert(i+c==n-1 && "Equation has no solution");
return false;
}
for(k=0;k<=n;k++){
swap(x[i][k], x[i+c][k]);
}
return true;
}
}
return true;
}
//Gauss Jordan elimination method
void GaussJordan(float x[][N], int n){
int i, j, k, c;
float rat;
for(i=0;i<n;i++){
//not taking the zero in pivot column case
chk_zero(x, n, i);
normalize(x, n, i, i);
for(j=0;j<n;j++){
if (i != j){
float fac{x[j][i]};
for(k=0;k<=n;k++)
x[j][k] = x[j][k]-fac*x[i][k];
}
}
}
}
int main(){
float arr[][N] = { {0, 5, 1, 2},
{2, 11, 5, 3},
{1, 0, 0, 0} };
int n = sizeof(arr)/sizeof(arr[0]);
print(arr, n);
GaussJordan(arr, n);
cout << n << endl;
print(arr, n);
return 0;
}
我得到的输出是:
1 0 0 2.3842e-08
0 1 0 0.5
-0 -0 1 -0.5
我应该得到的输出是:
1 0 0 0
0 1 0 0.5
-0 -0 1 -0.5
值 2.3842e-08 应为零。是因为C++中浮点数的精度吗?
如果是这样,我应该怎么做才能在不丢失数据的情况下将如此低的值舍入为 0?
另外,为什么是“-0”而不是 0。
The value 2.3842e-08 should be a zero. Is it because of the precision of the floating point in C++ ?
是的,是的。
If so, what should I do in order to round such low values to 0 without loss of data ?
您可以使用 epsilon
值来决定浮点值是否被视为 0:
const float epsilon = 0.000001; // Depends on the use case of your application
if (std::abs(some_float) < epsilon) {
// Treat some_float as 0
}
但是,这种方法有一些缺点。阅读 here 了解更多。
Also, why is there a "-0" instead of a 0.
这是因为浮点数的表示方式。大多数 C++ 编译器使用 IEEE 754 标准来实现浮点运算。
补充几点(与问题无关):
- 您应该避免使用
using namespace std
,因为它会污染全局命名空间。特别是对于大型代码库。 - 使用
std::array<>
而不是原始数组,因为它们更安全。
The value 2.3842e-08 should be a zero. Is it because of the precision of the floating point in C++ ?
没有。根据 IEEE-754 标准,它是二进制数字系统中浮点数表示的一个特征。它是在硬件中实现的,几乎所有语言都在使用它。所有的浮点计算都带有错误,因此您应该为 FPU 设置正确的舍入模式。有关详细信息,请参阅