直接切入正题,最近需要将matlab转成c++集成到项目做成调用dll来做,查了常用的matlab转成c++的方法。说的最多的就是使用matlab coder,这是matlab自带的转换工具,但是研究过matlab coder之后,果断放弃了这种思路,原因是matlab coder很多的matlab自带函数都无法支持,完全不能满足我项目的要求。
有人说,为啥不使用联编的方式,联编需要调用matlab引擎。仍然不能脱离matlab。matlab付费,而且相比直接使用c++实现相同功能时,调用c++可以在调用速度上实现质的提高。
首先,介绍一个c++库—armodillo(C++ library for linear algebra & scientific computing),这样就能在c++中使用类似matlab中的向量矩阵等类型,并且提供了矩阵的操作函数和matlab中的一些函数(具体功能和使用,官网上都有,不过是英文)。
话不多说,我第一次尝试转换的是matlab中的kstest2函数(ks检验),贴的代码中没有做判断逻辑,但是主逻辑都实现了,说下思路,首先,要先找到matlab函数的源码(type 函数名),然后看懂matlab源码中想表达的意思,使用armodillo中对应的类型和方法对应编程就行,很简单。下面贴一个我最初的ks函数(并不完整,但能运行,结果和matlab一样),当然,现在我转换的功底已经有点了(嘿嘿,有些原因,成熟的算法不能发布,但是思想最重要哦)
#include <iostream>
#include <armadillo>
#include <vector>
#include<fstream>
#include <string>
#pragma warning(disable:4996)
using namespace std;
using namespace arma;
void kstest2(vec A, vec B, double alpha, int tail)
{
//double alpha = 0.05;
//int tail = 0;
//colvec A;
//A << 1 << endr << 3 << endr << 2 << endr;
//colvec B;
//B << 2 << endr;
vec I1;
I1 << -INFINITY << endr;
vec I2;
I2 << INFINITY << endr;
vec binEdges;
binEdges = join_cols(join_cols(I1, sort(join_cols(A, B))), I2);
uvec binCounts1 = histc(A, binEdges);
uvec binCounts2 = histc(B, binEdges);
vec sumCounts1(binCounts1.size());
uvec sum1 = cumsum(binCounts1);
double sum2 = sum(binCounts1);
for (int i = 0; i < binCounts1.size(); i++)
{
sumCounts1(i) = sum1(i, 0) / sum2;
}
vec sumCounts2(binCounts2.size());
uvec sum3 = cumsum(binCounts2);
double sum4 = sum(binCounts2);
for (int i = 0; i < binCounts2.size(); i++)
{
sumCounts2(i) = sum3(i, 0) / sum4;
}
sumCounts1.resize(sumCounts1.size() - 1);
sumCounts2.resize(sumCounts2.size() - 1);
vec sampleCDF1 = sumCounts1;
vec sampleCDF2 = sumCounts2;
vec deltaCDF = abs(sampleCDF1 - sampleCDF2);
double KSstatistic = (double)max(deltaCDF);
cout<<"KSstatistic=" << KSstatistic<<endl;
double n1 = A.size();
double n2 = B.size();
double n = n1 * n2 / (n1 + n2);
double lambda = (sqrt(n) + 0.12 + 0.11 / sqrt(n)) * KSstatistic;
vec j = linspace<vec>(1, 101, 101);
j = j - 1;
for (int i = 0; i < j.size(); i++)
{
j(i) = (double)pow(-1, j(i));
}
vec j1 = exp(pow(linspace<vec>(1, 101, 101), 2)*(-2 * lambda*lambda));
for (int i = 0; i < j.size(); i++)
{
j1(i) = j(i)*j1(i);
}
double pValue = 2 * sum(j1);
pValue = min(max(pValue, 0.0), 1.0);
cout<<"pValue="<<pValue<<endl;
int H = (alpha >= pValue);
cout<<"H="<<H;
}
int main()
{
vector<double> vec1;
vec1.push_back(1);
vec1.push_back(100);
vec1.push_back(2);
vector<double> vec2;
vec2.push_back(1);
vec2.push_back(3);
vector<double> vec1;
vector<double> vec2;
vec A(vec1);
vec B(vec2);
kstest2(A, B, 0.05, 0);
return 1;
}
输入的方式多种多样,我大概研究了四种,,在代码中写了两种,文档中都有,根据需要来做吧。
当然,运行之前需要配置armodillo的环境,夜已深,还有其他重要事要做,嘿嘿,安装的部分我之后再写吧。