最近我问了相似问题,但是算法是用Python实现的。现在我尝试实现相同的算法,但是在C++中(我对它非常陌生):
#include<iostream>
#include<cstdlib>
#include<ctime>
#include<cmath>
#include <tgmath.h>
using namespace std;
const int MAXRANGE = 1000;
int randint(int low, int high){
return rand() % (high - low) + low;
}
void generate_vector(float vec[],int dimension){
for (int i = 0; i < dimension; i++){
vec[i] = randint(-MAXRANGE,MAXRANGE);
}
// We need to ensure that the last entry doesn't equal to zero
if (vec[dimension-1] == 0){
while (vec[dimension-1] == 0){
vec[dimension-1] = randint(-MAXRANGE,MAXRANGE);
}
}
}
void generate_orthogonal (float *vector, float orthogonal_vector[], int dimension){
float last_entry;
float dot_product = 0;
for (int i = 0; i < dimension -1; i++){
orthogonal_vector[i] = randint(-MAXRANGE,MAXRANGE);
}
for (int i = 0; i < dimension -1; i++){
dot_product = dot_product + (vector[i] * orthogonal_vector[i]);
}
last_entry = -(dot_product/vector[dimension-1]);
orthogonal_vector[dimension-1] = last_entry;
}
float dot_product(float *vector1, float vector2[],int dimension){
float sum = 0;
for (int i = 0; i < dimension; i++){
sum += (vector1[i])*(vector2[i]);
}
return sum;
}
void print_vector(float *A,int dim){
cout << "(";
for (int i = 0; i < dim; i++){
if (i == dim -1){
cout << A[i];
}
else{
cout << A[i] << ",";}
}
cout << ")^T" << endl;
}
int main(){
srand(time(0));
int dimension;
cout << "Choose dimension for the vector: ";
cin >> dimension;
float arbitrary_vector[dimension], orthogonal[dimension];
generate_vector(arbitrary_vector,dimension);
generate_orthogonal(arbitrary_vector,orthogonal,dimension);
cout << "First vector: ";
print_vector(arbitrary_vector,dimension);
cout << "Orthogonal vector: ";
print_vector(orthogonal,dimension);
cout << "Dot product of the vectors: ";
cout << dot_product(arbitrary_vector,orthogonal,dimension) << endl;
}还有什么可以改进的?
正如一些人之前指出的,如果第一个向量的最后一个条目是0,则该算法会抛出异常。我做了一个小小的修改,以确保generate_vector函数不会生成最后一个元素为零的向量。
发布于 2019-09-22 11:58:52
欢迎来到C++。
不过,您似乎或多或少地试图编写C代码,而不是C++。让我们看看您可以改进什么:
using namespace std;,这是一个可怕的做法,使你陷入麻烦真的很快。std::并不难打字,所以尽早养成这个习惯。constexpr使用它们dot_product函数已在标准库中实现。它被称为inner_product。因此,下面的代码可以用下面的代码( (vector1我)*(vector2我);(a.cbegin(),a.cend(),b.cbegin(),float (0.0))替换为vector2[],int维数= 0;for (int i= 0;i<维度;i++){ sum += }返回和;}。generate函数。请注意,C++在<random>头中有各种好的随机数生成器(rand()不是其中之一)。我不知道为什么要用整数来表示浮点向量,但是你可以很容易地适应。编辑:由@L.F.发现的合并问题。#包括 #包括类randomStreamUniformInt { public:显式randomStreamUniformInt(int lower_bound,int upper_bound):mt(std::random_device {} ()),uniform_dist(lower_bound,upper_bound) {显randomStreamUniformInt(int lower_bound,int upper_bound,double种子):mt(种子),uniform_dist(lower_bound,upper_bound) {} int运算符() (){返回uniform_dist(mt);std::mt19937_64 mt;std::uniform_int_distribution<> uniform_dist;};静态randomStreamUniformInt rng(-MAXRANGE,MAXRANGE);std::vector生成随机(const std::size_t numElements) { std::vector res(numElements);std: generate (res.begin(),res.end(),rng);返回res;}将随机数生成器作为参数而不是全局变量传递会更好。我把它作为一个练习。std::vector或std::array )使用标准工具,具体取决于编译时是否知道大小。因此,下面的代码: float arbitrary_vector尺寸,正交尺寸应该以std::vector arbitrary_vector =generate_random(维度)的形式写得更好;注意,将每个声明放在一行中总是更好。generate_orthogonal可以得到相应的改进。std::vector generate_orthogonal(const std::vector& a) { //获取一些随机数据std::vector b= generate_random(a.size());//查找a //中最后一个非零项,我们必须通过std将反向迭代器转换为迭代器::prev(rit.base()) auto = const浮子f -> bool {返回f == float(0.0);};auto end = std::prev(std::find_if_not(a.crbegin(),a.crend(),IsZero).base();//确定到结束浮点数dot_product =std::inner_product的点积(a.cbegin(),end,b.cbegin(),float(0.0));//设置b的值,使内积bA.cbegin(),结束) =- dot_product / (* end );返回b};所以把它放在一起,看起来会是这样的:
#include <algorithm>
#include <random>
#include <vector>
constexpr int MAXRANGE = 1000;
class randomStreamUniformInt {
public:
explicit randomStreamUniformInt(int lower_bound, int upper_bound)
: mt(std::random_device{}()), uniform_dist(lower_bound, upper_bound) {}
explicit randomStreamUniformInt(int lower_bound, int upper_bound, double seed)
: mt(seed), uniform_dist(lower_bound, upper_bound) {}
int operator() () { return uniform_dist(mt); }
private:
std::mt19937_64 mt;
std::uniform_int_distribution<> uniform_dist;
};
static randomStreamUniformInt rng(-MAXRANGE, MAXRANGE);
std::vector<float> generate random(const std::size_t numElements) {
std::vector<float> res(numElements);
std::generate(res.begin(), res.end(), rng);
return res;
}
std::vector<float> generate_orthogonal(const std::vector<float>& a) {
// get some random data
std::vector<float> b = generate_random(a.size());
// find the last non zero entry in a
// We have to turn the reverse iterator into an iterator via std::prev(rit.base())
auto IsZero = [] (const float f) -> bool { return f == float(0.0);};
auto end = std::prev(std::find_if_not(a.crbegin(), a.crend(), IsZero).base());
// determine the dot product up to end
float dot_product = std::inner_product(a.cbegin(), end, b.cbegin(), float(0.0));
// set the value of b so that the inner product is zero
b[std::distance(a.cbegin(), end)] = - dot_product / (*end);
return b;
}
int main() {
std::size_t dimension = 20;
std::vector<float> a = generate_random(dimension);
std::vector<float> b = generate_orthogonal(a);
}https://codereview.stackexchange.com/questions/229457
复制相似问题