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;
}
Related
I am trying to solve the generalized eigenvalue problem for the hydrogen atom by using LAPACKE_dsygvd. For the parameters of the generator functions, I use an interval that starts at 0.01 and takes N steps of 0.01. What I change is the value of N. Everythings fine for N = 14 and below, where I get the answers from the analytical solution. However, when I choose N = 15 and above, I get an error and info is returned with a value > N. After reading the documentation from LAPACK, it says the following:
N: if INFO = N + i, for 1 <= i <= N, then the leading
minor of order i of B is not positive definite.
The factorization of B could not be completed and
no eigenvalues or eigenvectors were computed.
But I have checked my matrix B and it is positive definite. I don't know what is wrong.
Below I show my scripts
#include <cmath>
#include <cstdio>
#include <stdio.h>
#include <stdlib.h>
#include <iostream>
#include "library.h"
#include "mkl.h"
using namespace std;
double Superposition(const double ai, const double aj, const int m);
double Hamiltonian(const double ai, const double aj, const int m);
void print_matrix(double *A, int n) {
for (int i = 0; i < n; i++) {
for (int j = 0; j < n; j++) {
printf("%.7f ", A[i*n + j]);
}
cout << "\n";
}
}
void print_vector(double *vec, int n) {
for (int i = 0; i < n; i++) {
cout << vec[i] << " ";
}
cout << "\n";
}
double* interval(double min, double step) {
double *result;
result = (double *)mkl_malloc( N*sizeof( double ), 64 );
for (int i = 0; i < N; i++) {
result[i] = min + i*step;
}
return result;
}
int main() {
cout << Ry << "\n";
double *S, *H, *I, *eigenvalues;
double alpha, beta;
int i, j, info;
char* uplo = "U"; char* jobz = "V";
I = interval(0.01, 0.01);
alpha = 1.0; beta = 0.0;
S = (double *)mkl_malloc( N*N*sizeof( double ), 64 );
H = (double *)mkl_malloc( N*N*sizeof( double ), 64 );
eigenvalues = (double *)mkl_malloc( N*sizeof( double ), 64 );
for (i = 0; i < N; i++) {
for (j = 0; j < N; j++) {
int index = i*N + j;
if (j < i) {
S[index] = 0.0;
H[index] = 0.0;
}
else {
S[index] = Superposition(I[i], I[j], m);
H[index] = Hamiltonian(I[i], I[j], m);
}
}
}
print_matrix(S, N); cout << "\n";
print_matrix(H, N); cout << "\n" << "\n";
info = LAPACKE_dsygv(LAPACK_ROW_MAJOR, 1, *jobz, *uplo, N,
H, N, S, N, eigenvalues);
//print_matrix(H, N); cout << "\n";
//for (i = 0; i < N; i++) {
// eigenvalues[i] /= Ry;
//}
cout << info << "\n" << "\n";
print_matrix(H, N); cout << "\n";
print_vector(eigenvalues, N);
mkl_free(S);
mkl_free(H);
mkl_free(I);
mkl_free(eigenvalues);
}
*Edit: I used dsygvd as included in MKL, and the same error doesn't occur. However, I get very different results for both functions using the same inputs.
I am trying to write a c++ code which calculates an Integration b/n two numbers (a,b).
I wrote the following sequential code, but what I need to know is what is the best way to parellelize this code in order to generate the random numbers in a faster way. And is this random number generator in c++ thread safe?
The integration formula I am using is:
I = sum(f(xi))*dx and dx =(b-a)/n
double fun(double x) //f(x) = x;
{
return x;
}
double MonteCarloIntegration (double a, double b, int n)
{
if(a > b){
return MonteCarloIntegration(b, a, n);
}
double sum = 0.0;
double r= 0.0;
for (int i = 1; i <= n; i++)
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> dis(0.0, 1.0);
r = dis(gen);
sum = sum + fun(a+((b-a)*r));
}
sum = ((b-a)/n)*sum;
return sum;
}
int main(int argc,char * argv[]) {
if (argc < 2) {
std::cerr << "use: " << argv[0]
<< " Numer_of_Random_samples (n) \n";
std::cerr << " Example:\n " << argv[0] << " 1000000 \n\n";
return -1;
}
double b = 4.0; //lower bound
double a = 7.0; //upper bound
int n = atoi(argv[1]);
std::cout <<MonteCarloIntegration(a,b,n);
return 0;
}
Here I have rewritten your code to use OpenMP
#include <random>
#include <iostream>
double fun(double x) //f(x) = x;
{
return x;
}
double MonteCarloIntegration (double a, double b, int n)
{
std::random_device rd;
std::mt19937 gen(rd());
std::uniform_real_distribution<double> dis(0.0, 1.0);
if(a > b)
{
return MonteCarloIntegration(b, a, n);
}
double sum = 0.0;
#pragma omp parallel for reduction(+:sum)
for (int i = 1; i <= n; i++)
{
double r = dis(gen);
sum = sum + fun(a+((b-a)*r));
}
sum = ((b-a)/n)*sum;
return sum;
}
int main(int argc,char * argv[]) {
if (argc < 2)
{
std::cerr << "use: " << argv[0]
<< " Numer_of_Random_samples (n) \n";
std::cerr << " Example:\n " << argv[0] << " 1000000 \n\n";
return -1;
}
double b = 4.0; //lower bound
double a = 7.0; //upper bound
int n = atoi(argv[1]);
std::cout << MonteCarloIntegration(a,b,n) << std::endl;
return 0;
}
Compile this way
g++ -O3 -fopenmp integrate-mc.cxx -std=c++11 -o integrate-mc
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];.
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.
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.