将Python更改为C++:如何消除矢量中不断出现的零

Changing Python to C++: how to eliminate zeros that are keep appearing in vectors

本文关键字:Python C++ 何消      更新时间:2023-10-16

我正试图将这段Python代码更改为C++,但在编译时,不需要的零不断出现。为什么会发生这种情况,我该如何解决这个问题?

p = [0.2, 0.2, 0.2, 0.2, 0.2]
world = ['green', 'red', 'red', 'green', 'green']
measurements = ['red', 'green']
motions = [1,1]
pHit = 0.6
pMiss = 0.2
pExact = 0.8
pOvershoot = 0.1
pUndershoot = 0.1
def sense(p, Z):
q=[]
for i in range(len(p)):
hit = (Z == world[i])
q.append(p[i] * (hit * pHit + (1-hit) * pMiss))
s = sum(q)
for i in range(len(q)):
q[i] = q[i] / s
return q
def move(p, U):
q = []
for i in range(len(p)):
s = pExact * p[(i-U) % len(p)]
s = s + pOvershoot * p[(i-U-1) % len(p)]
s = s + pUndershoot * p[(i-U+1) % len(p)]
q.append(s)
return q
for k in range(len(measurements)):
p = sense(p, measurements[k])
p = move(p, motions[k])
print p

下面是我的C++实现代码:

#include <iostream>
#include <vector>
#include <string>
using namespace std;
vector<float> p (5);
vector<string> world (5);
vector<string> measurements (2);
vector<int> motions (2);
float pHit;
float pMiss;
float pExact;
float pOvershoot;
float pUndershoot;
vector<float> sense(vector<float> p, string Z);
vector<float> move(vector<float> p, int U);
int main(){
vector<float> p (5, 0.2);
world.push_back("green");
world.push_back("red");
world.push_back("red");
world.push_back("green");
world.push_back("green");
measurements.push_back("red");
measurements.push_back("green");
pHit = 0.6;
pMiss = 0.2;
pExact = 0.8;
pOvershoot = 0.1;
pUndershoot = 0.1;
vector<int> motions (2, 1);
for(int i=0; i<measurements.size(); i++){
p = sense(p, measurements[i]);
p = move(p, motions[i]);
}
for(int i=0; i<p.size(); i++){
cout << p[i] << " ";
}
return 0;
}
vector<float> sense(vector<float> p, string Z){
vector<float> q (p.size());
for(int i=0; i<p.size(); i++){
bool hit = (Z == world[i]);
q.push_back(p[i] * (hit * pHit + (1-hit) * pMiss));
}
float s = 0.0;
for(int i=0; i<q.size(); i++){
s += q[i];
}
for(int i=0; i<q.size(); i++){
q[i] /= s;
}
return q;
}
vector<float> move(vector<float> p, int U){
vector<float> q (p.size());
for(int i=0; i<p.size(); i++){
float s = pExact * p[(i-U) % p.size()];
s = s + pOvershoot * p[(i-U-1) % p.size()];
s = s + pUndershoot * p[(i-U+1) % p.size()];
q.push_back(s);
}
return q;
}

*期望输出:[0.21157894736842103、0.1515789473684211、0.08105263157894739、0.1684210526315789.7、0.3873684210526316]

*我的输出:0 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0 0 0 0 00 0 0 0

在Pythonsense:中

def sense(p, Z):
q=[]

你在声明一个空列表。

而在C++sense:中

vector<float> sense(vector<float> p, string Z){
vector<float> q (p.size());

你声明了一个给定大小的向量,然后在它上使用push_back。这会改变大小,并在开始时留下零值。

只需:

vector<float> q;

然后你可以用保留内存

q.reserve(p.size());

(reserve不是resize,它在内部分配,但不会更改.size()),所以push_back不需要那么多重新分配。

一旦解决了这个问题,就可以对具有完全相同问题的move函数应用完全相同的修复。

使用c++17,您可以使代码看起来非常像python的对应代码:

#include <initializer_list>
#include <vector>
#include <numeric>
#include <algorithm>
#include <functional>
#include <iostream>
#include <string>
using namespace std::literals;
auto p = std::vector{0.2, 0.2, 0.2, 0.2, 0.2};
auto world = std::vector{"green"s, "red"s, "red"s, "green"s, "green"s};
auto measurements = std::vector{"red"s, "green"s};
auto motions = std::vector{1,1};
auto pHit = 0.6;
auto pMiss = 0.2;
auto pExact = 0.8;
auto pOvershoot = 0.1;
auto pUndershoot = 0.1;
auto sum = [](auto&& cont)
{
using value_type = std::decay_t<decltype(*std::begin(cont))>;
return std::accumulate(std::begin(cont), std::end(cont),
value_type(0), std::plus<>());
};
auto divide_all = [](auto&& container, auto&& divisor)
{
for(auto&& val : container)
val /= divisor;
};
auto sense = [](auto p, auto && Z)
{
for(auto&& val : p)
{
auto i = std::distance(&p[0], &val); 
auto hit = double(Z == world[i]);
val *= (hit * pHit + (1-hit) * pMiss);
}
divide_all(p, sum(p));
return p;
};
auto move = [](auto p, auto&& U)
{
auto size = std::size(p);
for(std::size_t i = 0 ; i < size ; ++i)
{
auto s = pExact * p[(i-U) % size];
s = s + pOvershoot * p[(i-U-1) % size];
s = s + pUndershoot * p[(i-U+1) % size];
p[i] = s;
}
return p;
};
template<class Container>
void print(Container&& cont)
{
std::cout << "[";
const char* sep = " ";
for (auto&& x : cont) {
std::cout << sep << x;
sep = ", ";
}
std::cout << " ]" << std::endl;
}
int main()
{
for(std::size_t k = 0 ; k < std::size(measurements) ; ++k)
{
p = move(sense(p, measurements[k]), motions[k]);
}
std::cout << __TIMESTAMP__ << std::endl;
print(p);
}

尽管我得到的结果略有不同。我可能在翻译中遗漏了一些东西:

Thu Oct 12 21:37:26 2017
[ 0.231391, 0.217253, 0.207143, 0.216875, 0.223073 ]

http://coliru.stacked-crooked.com/a/f973d6c5eab3c746