C++ 如何检查两个矩阵是否相同?
这个想法是将两个矩阵相乘。并使用特征值进行相同的乘法,然后检查结果是否相同 在下面的示例中,makeC++ 如何检查两个矩阵是否相同?,c++,c++11,matrix,c++14,eigen,C++,C++11,Matrix,C++14,Eigen,这个想法是将两个矩阵相乘。并使用特征值进行相同的乘法,然后检查结果是否相同 在下面的示例中,makeN=2返回相同的东西,但N=1000返回不相同的东西。为什么? #include <cstdlib> #include <iostream> #include <Eigen/Dense> using namespace std; using namespace Eigen; const int N = 1000; void mult_matrix(doub
N=2
返回相同的东西
,但N=1000
返回不相同的东西
。为什么?
#include <cstdlib>
#include <iostream>
#include <Eigen/Dense>
using namespace std;
using namespace Eigen;
const int N = 1000;
void mult_matrix(double x[N][N], double y[N][N], double z[N][N]) {
int rows = N;
int cols = N;
for (int i = 0; i < rows; i++)
for (int j = 0; j < cols; j++)
for (int k = 0; k < cols; k++)
z[i][j] += x[i][k] * y[k][j];
}
void check(double *x, double *y, double *z) {
Matrix<double, Dynamic, Dynamic, RowMajor> m =
Matrix<double, Dynamic, Dynamic, RowMajor>::Map(x, N, N) *
Matrix<double, Dynamic, Dynamic, RowMajor>::Map(y, N, N);
cout << m(0, 0) << endl;
cout << Matrix<double, Dynamic, Dynamic, RowMajor>::Map(z, N, N)(0, 0) << endl;
if (m == Matrix<double, Dynamic, Dynamic, RowMajor>::Map(z, N, N))
cout << "same thing" << endl;
else
cout << "NOT same thing" << endl;
}
int main() {
double *a = (double*)malloc(N*N*sizeof(double));
double *b = (double*)malloc(N*N*sizeof(double));
double *c = (double*)malloc(N*N*sizeof(double));
Matrix<double, Dynamic, Dynamic, RowMajor>::Map(a, N, N).setRandom();
Matrix<double, Dynamic, Dynamic, RowMajor>::Map(b, N, N).setRandom();
Matrix<double, Dynamic, Dynamic, RowMajor>::Map(c, N, N).setZero();
mult_matrix((double (*)[N])a, (double (*)[N])b, (double (*)[N])c);
check(a, b, c);
}
#包括
#包括
#包括
使用名称空间std;
使用名称空间特征;
常数int N=1000;
void mult_矩阵(双x[N][N],双y[N][N],双z[N][N]){
int行=N;
int cols=N;
对于(int i=0;i cout由于舍入错误,将浮点数与=
运算符进行比较会出现错误。因此对于N=2
,它可能会工作,但对于较大的N
,它很可能会失败
尝试以下比较器,而不是==
:
bool double_equals(double a, double b, double epsilon = 0.001)
{
return std::abs(a - b) < epsilon;
}
bool double_等于(双a,双b,双ε=0.001)
{
返回std::abs(a-b)
以下是@Jonathan Leffler的评论,上面的比较器并不理想,因为使用相对差比绝对差更好
double reldiff(double a, double b) {
double divisor = fmax(fabs(a), fabs(b)); /* If divisor is zero, both x and y are zero, so the difference between them is zero */
if (divisor == 0.0) return 0.0; return fabs(a - b) / divisor;
}
bool double_equals(double a, double b, double rel_diff)
{
return reldiff(a, b) < rel_diff;
}
double reldiff(双a,双b){
双除数=fmax(fabs(a),fabs(b));/*如果除数为零,x和y都为零,那么它们之间的差值为零*/
if(除数==0.0)返回0.0;返回fabs(a-b)/除数;
}
布尔双_等于(双a,双b,双相对差)
{
返回reldiff(a,b)
由于舍入错误,将浮点数与=
运算符进行比较会出现错误。因此对于N=2
,它可能会工作,但对于较大的N
,它很可能会失败
尝试以下比较器,而不是==
:
bool double_equals(double a, double b, double epsilon = 0.001)
{
return std::abs(a - b) < epsilon;
}
bool double_等于(双a,双b,双ε=0.001)
{
返回std::abs(a-b)
以下是@Jonathan Leffler的评论,上面的比较器并不理想,因为使用相对差比绝对差更好
double reldiff(double a, double b) {
double divisor = fmax(fabs(a), fabs(b)); /* If divisor is zero, both x and y are zero, so the difference between them is zero */
if (divisor == 0.0) return 0.0; return fabs(a - b) / divisor;
}
bool double_equals(double a, double b, double rel_diff)
{
return reldiff(a, b) < rel_diff;
}
double reldiff(双a,双b){
双除数=fmax(fabs(a),fabs(b));/*如果除数为零,x和y都为零,那么它们之间的差值为零*/
if(除数==0.0)返回0.0;返回fabs(a-b)/除数;
}
布尔双_等于(双a,双b,双相对差)
{
返回reldiff(a,b)
不是答案,但评论太长
坏消息是无法比较两个浮点值是否相等
由于表示的有限性,即有效位数的有限性,不可避免地会出现截断错误。例如,0.1
将不会精确地表示为0.1
,而是表示为类似0.999999999933
或0.1000000000002
(虚构值)的值。精确值可能取决于特定的基转换算法和舍入策略
在幸运的情况下,当您进行计算时,耳轴误差会逐渐累积,因此有效位数也会逐渐减少。因此,使用有界相对误差测试是否相等是有意义的,例如:
|a - b| < max(|a|, |b|).ε
| a-b |
其中ε
接近机器精度(对于单精度,约10^-7
)
但在不吉利的情况下,比如导数的数值计算,就会出现所谓灾难性相消的现象:当你减去两个附近的值时,精确的有效位数会急剧下降
例如(sin(1.000001)-sin(1))/0.000001=(0.84147104-0.84147100)/0.0000001=0.40000000
,而精确值应为0.5403023
当两个向量接近垂直时,矩阵乘积会发生灾难性的相消,相对误差准则就不起作用了
最糟糕的情况是,当你想检查一个数量是否为零时,比如在寻找一个函数的根时:“接近零”的值可以有任意数量级(想想同样问题的解决方案,当变量以米表示,然后以毫米表示)没有相对误差标准可以起作用,但即使绝对误差也不能起作用,除非你有关于震级的额外信息。没有通用比较器可以起作用。不是答案,但注释太长
坏消息是无法比较两个浮点值是否相等
由于表示的有限性,即有效位数的有限性,不可避免地会出现截断错误。例如,0.1
将不会精确地表示为0.1
,而是表示为类似0.999999999933
或0.1000000000002
(虚构值)的值。精确值可能取决于特定的基转换算法和舍入策略
在幸运的情况下,当您进行计算时,耳轴误差会逐渐累积,因此有效位数也会逐渐减少。因此,使用有界相对误差测试是否相等是有意义的,例如:
|a - b| < max(|a|, |b|).ε
| a-b |
其中ε
接近机器精度(对于单精度,约10^-7
)
但在不吉利的情况下,比如导数的数值计算,就会出现所谓灾难性相消的现象:当你减去两个附近的值时,精确的有效位数会急剧下降
例如(sin(1.000001)-sin(1))/0.000001=(0.84147104-0.84147100)/0.0000001=0.40000000
,而精确值应为0.5403023