std::accumulate not acting as expected - c++

I am getting an unexpected result using std::accumulate with test code. I am trying to add up a large vector of doubles but for some reason the value is overflowing:
#include <iostream>
#include <vector>
#include <functional>
#include <numeric>
using namespace std;
double sum(double x, double y)
{
// slows things down but shows the problem:
//cout << x << " + " << y << endl;
return (x+y);
}
double mean(const vector<double> & vec)
{
double result = 0.0;
// works:
//vector<double>::const_iterator it;
//for (it = vec.begin(); it != vec.end(); ++it){
// result += (*it);
//}
// broken:
result = accumulate(vec.begin(), vec.end(), 0, sum);
result /= vec.size();
return result;
}
int main(int argc, char ** argv)
{
const unsigned int num_pts = 100000;
vector<double> vec(num_pts, 0.0);
for (unsigned int i = 0; i < num_pts; ++i){
vec[i] = (double)i;
}
cout << "mean = " << mean(vec) << endl;
return 0;
}
Partial output from the cout inside the sum:
2.14739e+09 + 65535
2.14745e+09 + 65536
-2.14748e+09 + 65537
-2.14742e+09 + 65538
-2.14735e+09 + 65539
Correct output (iterating):
mean = 49999.5
Incorrect output (using accumulate):
mean = 7049.5
I am probably making a tired mistake? I have used accumulate successfully before...
Thanks

You need to pass a double to accumulate:
result = accumulate(vec.begin(), vec.end(), 0.0, sum);
^^^
otherwise the accumulation is performed using int, and then converting the result to a double.

Related

No operator "+" matches these operands, aka cannot add Array<double> to double

Array<double> times[99];
time_t start, end;
double dif;
for (int i = 0; i < 100; i++) {
time(&start);
A.insertionSort();
time(&end);
dif = difftime(end, start);
times[i] = dif;
}
double mean;
double sum;
double stdDev;
for (int i = 0; i < 100; i++) {
sum = sum + times[i];
}
mean = sum / 100;
for (int i = 0; i < 100; i++) {
stdDev = stdDev + pow(times[i] - mean, 2);
}
stdDev = sqrt(stdDev / 100);
cout << "Mean: " << mean << endl;
cout << "Standard deviation: " << stdDev << endl;
I don't understand why it's not letting me add Sum + times[index] and times[index] - mean, that's where I'm getting the error you see in the title.
A portion of my header file in case this helps:
#define ARRAY_H
#include <iostream>
#include <stdlib.h>
#include <cmath>
#include <ctime>
using namespace std;
template <typename T>
class Array {
public:
Array() {}
Array(double) {}
Array<double> times[99]; is a C style array of 99 copies of Array<double>.
Array<double> seems to be a useless type.
Replace that line with double times[99];.

Param not changing for std::chi_squared_distribution

As per the answer to this question I have attempted to change the parameter of a distribution in <random> by using .param(). Below is a toy example where I'm trying to do this.
For both a chi-squared and a normal distribution I have a function that generates two values, the second where the parameter has been changed by .param(). I run both functions multiple times and print out the mean outcome for both. As expected the normal function produces mean outcomes of 0 and 10. Unexpectedly the chi-squared function produces mean outcomes of 4 and 4, instead of my expectation of 4 and 3. Why are my expectations off for the chi-squared distribution?
#include <iostream>
#include <random>
#include <vector>
using namespace std;
vector<double> chisqtest(mt19937_64 &gen)
{
vector<double> res(2);
chi_squared_distribution<double> chisq_dist(4);
res[0] = chisq_dist(gen);
chisq_dist.param(std::chi_squared_distribution<double>::param_type (3));
res[1] = chisq_dist(gen);
return res;
}
vector<double> normtest(mt19937_64 &gen)
{
vector<double> res(2);
normal_distribution<double> norm_dist(0,1);
res[0] = norm_dist(gen);
norm_dist.param(std::normal_distribution<double>::param_type (10,1));
res[1] = norm_dist(gen);
return res;
}
int main() {
unsigned int n = 100000;
mt19937_64 gen(1);
vector<double> totals = {0,0}, res(2);
for(unsigned int i = 0; i < n; i++){
res = chisqtest(gen);
totals[0] += res[0];
totals[1] += res[1];
}
cout << totals[0]/n << " " << totals[1]/n << "\n";
vector<double> totals2 = {0,0}, res2;
for(unsigned int i = 0; i < n; i++){
res2 = normtest(gen);
totals2[0] += res2[0];
totals2[1] += res2[1];
}
cout << totals2[0]/n << " " << totals2[1]/n << "\n";
}

standard deviation without mean c++

I have a functioning program to find the standard deviation of many integers. However, I am to find a way to get the standard deviation without the mean.
I understand the formula is:
std dev = sqrt [(B - A^2/N)/N]
where
A is the sum of the data values;
B is the sum of the squared data values;
N is the number of data values.
but how would I write that in code?
This is my function for the deviation but it uses the mean:
float calculateSD(int arr[])
{
float sum = 0.0, mean, standardDeviation = 0.0;
int i;
for(i = 0; i < SIZE; ++i)
{
sum += arr[i];
}
mean = sum/SIZE;
for(i = 0; i < SIZE; ++i)
//convert standardDeviation to float
standardDeviation += static_cast<float>(pow(arr[i] - mean, 2));
//return standard deviation
return sqrt(standardDeviation / SIZE);
}
#include <iostream>
#include <vector>
#include <numeric>
#include <math.h>
double stddev(std::vector<int> const& data)
{
auto stats = std::make_pair(0.0,0.0);
stats = std::accumulate(data.begin(), data.end(), stats,
[](std::pair<double,double> stats, double x) {
stats.first += x;
stats.second += x * x;
return stats;
});
return sqrt((stats.second - pow(stats.first, 2.0) / data.size()) / data.size());
}
int main(int argc, const char *argv[])
{
std::cout << stddev({1,1,1,1}) << std::endl;
std::cout << stddev({1,2,1,2}) << std::endl;
std::cout << stddev({1,10,1,10}) << std::endl;
}

Convert vector<int> to integer

I was looking for pre-defined function for converting a vector of integers into a normal integer but i din't find one.
vector<int> v;
v.push_back(1);
v.push_back(2);
v.push_back(3);
Need this:
int i=123 //directly converted from vector to int
Is there a possible way to achieve this?
If elements of vector are digits:
int result = 0;
for (auto d : v)
{
result = result * 10 + d;
}
If not digits:
stringstream str;
copy(v.begin(), v.end(), ostream_iterator<int>(str, ""));
int res = stoi(str.str());
Using C++ 11:
reverse(v.begin(), v.end());
int decimal = 1;
int total = 0;
for (auto& it : v)
{
total += it * decimal;
decimal *= 10;
}
EDIT: Now it should be the right way.
EDIT 2: See DAle's answer for a shorter/simpler one.
For the sake of wrapping it into a function to make it re-usable. Thanks #Samer
int VectorToInt(vector<int> v)
{
reverse(v.begin(), v.end());
int decimal = 1;
int total = 0;
for (auto& it : v)
{
total += it * decimal;
decimal *= 10;
}
return total;
}
One liner with C++11 using std::accumulate():
auto rz = std::accumulate( v.begin(), v.end(), 0, []( int l, int r ) {
return l * 10 + r;
} );
live example
In conjunction with the answer provided by deepmax in this post Converting integer into array of digits and the answers provided by multiple users in this post, here is a complete test program with a function to convert an integer to a vector and a function to convert a vector to an integer:
// VecToIntToVec.cpp
#include <iostream>
#include <vector>
// function prototypes
int vecToInt(const std::vector<int> &vec);
std::vector<int> intToVec(int num);
int main(void)
{
std::vector<int> vec = { 3, 4, 2, 5, 8, 6 };
int num = vecToInt(vec);
std::cout << "num = " << num << "\n\n";
vec = intToVec(num);
for (auto &element : vec)
{
std::cout << element << ", ";
}
return(0);
}
int vecToInt(std::vector<int> vec)
{
std::reverse(vec.begin(), vec.end());
int result = 0;
for (int i = 0; i < vec.size(); i++)
{
result += (pow(10, i) * vec[i]);
}
return(result);
}
std::vector<int> intToVec(int num)
{
std::vector<int> vec;
if (num <= 0) return vec;
while (num > 0)
{
vec.push_back(num % 10);
num = num / 10;
}
std::reverse(vec.begin(), vec.end());
return(vec);
}
Working solution for negative numbers too!
#include <iostream>
#include <vector>
using namespace std;
template <typename T> int sgn(T val) {
return (T(0) < val) - (val < T(0));
}
int vectorToInt(vector<int> v) {
int result = 0;
if(!v.size()) return result;
result = result * 10 + v[0];
for (size_t i = 1; i < v.size(); ++i) {
result = result * 10 + (v[i] * sgn(v[0]));
}
return result;
}
int main(void) {
vector<int> negative_value = {-1, 9, 9};
cout << vectorToInt(negative_value) << endl;
vector<int> zero = {0};
cout << vectorToInt(zero) << endl;
vector<int> positive_value = {1, 4, 5, 3};
cout << vectorToInt(positive_value) << endl;
return 0;
}
Output:
-199
0
1453
Live Demo
The other answers (as of May '19) seem to assume positive integers only (maybe 0 too). I had negative inputs, thus, I extended their code to take into account the sign of the number as well.

Avoid blas when involving temporary memory allocation?

I have a program that computes the matrix product x'Ay repeatedly. Is it better practice to compute this by making calls to MKL's blas, i.e. cblas_dgemv and cblas_ddot, which requires allocating memory to a temporary vector, or is better to simply take the sum of x_i * a_ij * y_j? In other words, does MKL's blas theoretically add any value?
I benchmarked this for my laptop. There was virtually no difference in each of the tests, other than g++_no_blas performed twice as poorly as the other tests (why?). There was also no difference between O2, O3 and Ofast.
g++_blas_static 57ms
g++_blas_dynamic 58ms
g++_no_blas 100ms
icpc_blas_static 57ms
icpc_blas_dynamic 58ms
icpc_no_blas 58ms
util.h
#ifndef UTIL_H
#define UTIL_H
#include <random>
#include <memory>
#include <iostream>
struct rng
{
rng() : unif(0.0, 1.0)
{
}
std::default_random_engine re;
std::uniform_real_distribution<double> unif;
double rand_double()
{
return unif(re);
}
std::unique_ptr<double[]> generate_square_matrix(const unsigned N)
{
std::unique_ptr<double[]> p (new double[N * N]);
for (unsigned i = 0; i < N; ++i)
{
for (unsigned j = 0; j < N; ++j)
{
p.get()[i*N + j] = rand_double();
}
}
return p;
}
std::unique_ptr<double[]> generate_vector(const unsigned N)
{
std::unique_ptr<double[]> p (new double[N]);
for (unsigned i = 0; i < N; ++i)
{
p.get()[i] = rand_double();
}
return p;
}
};
#endif // UTIL_H
main.cpp
#include <iostream>
#include <iomanip>
#include <memory>
#include <chrono>
#include "util.h"
#include "mkl.h"
double vtmv_blas(double* x, double* A, double* y, const unsigned n)
{
double temp[n];
cblas_dgemv(CblasRowMajor, CblasNoTrans, n, n, 1.0, A, n, y, 1, 0.0, temp, 1);
return cblas_ddot(n, temp, 1, x, 1);
}
double vtmv_non_blas(double* x, double* A, double* y, const unsigned n)
{
double r = 0;
for (unsigned i = 0; i < n; ++i)
{
for (unsigned j = 0; j < n; ++j)
{
r += x[i] * A[i*n + j] * y[j];
}
}
return r;
}
int main()
{
std::cout << std::fixed;
std::cout << std::setprecision(2);
constexpr unsigned N = 10000;
rng r;
std::unique_ptr<double[]> A = r.generate_square_matrix(N);
std::unique_ptr<double[]> x = r.generate_vector(N);
std::unique_ptr<double[]> y = r.generate_vector(N);
auto start = std::chrono::system_clock::now();
const double prod = vtmv_blas(x.get(), A.get(), y.get(), N);
auto end = std::chrono::system_clock::now();
auto duration = std::chrono::duration_cast<std::chrono::milliseconds>(
end - start);
std::cout << "Result: " << prod << std::endl;
std::cout << "Time (ms): " << duration.count() << std::endl;
GCC no blas is poor because it does not use vectorized SMID instructions, while others all do. icpc will auto-vectorize you loop.
You don't show your matrix size, but generally gemv is memory bound. As the matrix is much larger than a temp vector, eliminating it may not be able to increase the performance a lot.