c++ Variance and Standard Deviation - c++

I have created a program that prompts a user to enter a data set. The program stores and sorts the data, then computes a variance and the standard deviation of the array. However, I am not getting the correct computations for variance and standard deviation (the answer is slightly off). Anyone know what the issue seems to be?
#include <iostream>
#include <iomanip>
#include <array>
using namespace std;
//function declarations
void GetData(double vals[], int& valCount);
void Sort(double vals[], int& valCount);
void printSort(double vals[], int& valCount);
double Variance(double vals[], int valCount);
double StandardDev(double vals[], int valCount);
double SqRoot(double value); //use for StandardDev function
//function definitions
int main ()
{
double vals = 0;
int valCount = 0; //number of values to be processed
//ask user how many values
cout << "Enter the number of values (0 - 100) to be processed: ";
cin >> valCount;
//process and store input values
GetData(&vals, valCount);
//sort values
Sort(&vals, valCount);
//print sort
cout << "\nValues in Sorted Order: " << endl;
printSort(&vals, valCount);
//print variance
cout << "\nThe variance for the input value list is: " << Variance(&vals, valCount);
//print standard deviation
cout << "\nThe standard deviation for the input list is: " <<StandardDev(&vals, valCount)<< endl;
return 0;
}
//prompt user to get data
void GetData(double vals[], int& valCount)
{
for(int i = 0; i < valCount; i++)
{
cout << "Enter a value: ";
cin >> vals[i];
}
}
//bubble sort values
void Sort(double vals[], int& valCount)
{
for (int i=(valCount-1); i>0; i--)
for (int j=0; j<i; j++)
if (vals[j] > vals[j+1])
swap (vals[j], vals[j+1]);
}
//print sorted values
void printSort(double vals[], int& valCount)
{
for (int i=0; i < valCount; i++)
cout << vals[i] << "\n";
}
//compute variance
double Variance(double vals[], int valCount)
{
//mean
int sum = 0;
double mean = 0;
for (int i = 0; i < valCount; i++)
sum += vals[i];
mean = sum / valCount;
//variance
double squaredDifference = 0;
for (int i = 0; i < valCount; i++)
squaredDifference += (vals[i] - mean) * (vals[i] - mean);
return squaredDifference / valCount;
}
//compute standard deviation
double StandardDev(double vals[], int valCount)
{
double stDev;
stDev = SqRoot(Variance(vals, valCount));
return stDev;
}
//compute square root
double SqRoot(double value)
{
double n = 0.00001;
double s = value;
while ((s - value / s) > n)
{
s = (s + value / s) / 2;
}
return s;
}

There was quite a bit wrong with the code that was causing your errors. Type mismatches, but more importantly, you never created an array to store the values. You treated a plain double like an array and got lucky your program never crashed on you.
Below is a working version of your code, verified with a made up data set and Excel. I left as much of your code there as possible, just commented out when appropriate. If I commented it out, I didn't make any changes to it, so there may still be errors.
Vector over array in this case. You don't know the size up front (at compile time), and vectors are easier than dynamic arrays. You also never had an array. Vectors also know how big they are, so you don't need to pass the size around.
Type mismatches. Your functions keep expecting an array of doubles, but your sum was an int, among many other mismatches. You were also passing a plain double like it was an array, writing in memory that wasn't yours to change like that.
Best practices to start now. Stop with using namespace std;. Just qualify your names when needed, or be more specific with lines like using std::cout; at the top of a function. Your naming was all over the place. Pick a naming scheme and stick with it. Names starting with a capital letter are generally reserved for classes or types.
#include <iomanip>
#include <iostream>
// #include <array> // You never actually declared a std::array
#include <vector> // You don't know the size ahead of time, vectors are the
// right tool for that job.
// Use what's available
#include <algorithm> // std::sort()
#include <cmath> // std::sqrt()
#include <numeric> // std::accumulate()
// function declarations
// Commented out redundant functions, and changed arguments to match
void get_data(std::vector<double>& vals);
// void Sort(double vals[], int& valCount);
void print(const std::vector<double>& vals);
double variance(const std::vector<double>& vals);
double standard_dev(const std::vector<double>& vals);
// double SqRoot(double value); //use for StandardDev function
// function definitions
int main() {
int valCount = 0; // number of values to be processed
// ask user how many values
std::cout << "Enter the number of values (0 - 100) to be processed: ";
std::cin >> valCount;
std::vector<double> vals(valCount, 0);
// Was just a double, but you pass it around like it's an array. That's
// really bad. Either allocate the array on the heap, or use a vector.
// Moved to after getting the count so I could declare the vector with
// that size up front instead of reserving later; personal preference.
// process and store input values
get_data(vals);
// sort values
// Sort(&vals, valCount);
std::sort(vals.begin(), vals.end(), std::less<double>());
// The third argument can be omitted as it's the default behavior, but
// I prefer being explicit. If compiling with C++17, the <double> can
// also be omitted due to a feature called CTAD
// print sort
std::cout << "\nValues in Sorted Order: " << '\n';
print(vals);
// print variance
std::cout << "\nThe variance for the input value list is: " << variance(vals);
// print standard deviation
std::cout << "\nThe standard deviation for the input list is: "
<< standard_dev(vals) << '\n';
return 0;
}
// prompt user to get data
void get_data(std::vector<double>& vals) {
for (unsigned int i = 0; i < vals.size(); i++) {
std::cout << "Enter a value: ";
std::cin >> vals[i];
}
}
// //bubble sort values
// void Sort(double vals[], int& valCount)
// {
// for (int i=(valCount-1); i>0; i--)
// for (int j=0; j<i; j++)
// if (vals[j] > vals[j+1])
// swap (vals[j], vals[j+1]);
// }
// print sorted values
void print(const std::vector<double>& vals) {
for (auto i : vals) {
std::cout << i << ' ';
}
std::cout << '\n';
}
// compute variance
double variance(const std::vector<double>& vals) {
// was int, but your now vector is of type double
double sum = std::accumulate(vals.begin(), vals.end(), 0);
double mean = sum / static_cast<double>(vals.size());
// variance
double squaredDifference = 0;
for (unsigned int i = 0; i < vals.size(); i++)
squaredDifference += std::pow(vals[i] - mean, 2);
// Might be possible to get this with std::accumulate, but my first go didn't
// work.
return squaredDifference / static_cast<double>(vals.size());
}
// compute standard deviation
double standard_dev(const std::vector<double>& vals) {
return std::sqrt(variance(vals));
}
// //compute square root
// double SqRoot(double value)
// {
// double n = 0.00001;
// double s = value;
// while ((s - value / s) > n)
// {
// s = (s + value / s) / 2;
// }
// return s;
// }
EDIT: I did figure out the variance with an accumulator. It does require knowledge of lambdas (anonymous functions, functors). I compiled to the C++14 standard, which has been the default of major compilers for a while now.
double variance(const std::vector<double>& vals) {
auto meanOp = [valSize = vals.size()](double accumulator, double val) {
return accumulator += (val / static_cast<double>(valSize));
};
double mean = std::accumulate(vals.begin(), vals.end(), 0.0, meanOp);
auto varianceOp = [mean, valSize = vals.size()](double accumulator,
double val) {
return accumulator +=
(std::pow(val - mean, 2) / static_cast<double>(valSize));
};
return std::accumulate(vals.begin(), vals.end(), 0.0, varianceOp);
}

mean = sum / valCount; in Variance will be computed using integer math, then converted to a double. You need to convert to double first:
mean = double(sum) / valCount;
Your SqRoot function calculates an approximate value. You should use std::sqrt instead which will be faster and more accurate.

Related

Confusion on push_back interaction with pair<float,int>

I have no error message instead I only have unexpected behavior.
double get_optimal_value(int capacity, vector<int> weights, vector<int> values) {
int n = weights.size();
vector<pair<double, int>> valuePerWeight(n);
pair<double,int> x;
for(int i = 0; i < n; i++){
double v = values[i]/weights[i];
x = make_pair(values[i]/weights[i], weights[i]);
valuePerWeight.push_back(x);
}
for(int i = 0; i < n && capacity > 0; i++){
int amount = min(capacity, valuePerWeight[i].second);
value += valuePerWeight[i].first * amount;
capacity -= amount;
}
double value = 0.0;
return value;
}
I am creating a vector with values of type pair<double,int>. I create the pair using make_pair(some_double, some_int), then I call push_back with the pair.
Later in the function I index into the vector and do stuff using the pairs.
However an issue arises, when I index into my valuePerWeight vector and retrieve the attributes of the different pairs. They all end up being zero regardless of index and regardless of .first or .second.
Through printing a bunch of variables I have asserted the created pair is not {0,0} but as soon as I push_back into the vector and index the pair and look at it's .first and .second attributes both are equal to 0.
I can't seem to understand why this is, originally I was using push_back seen as below
valuePerWeight.push_back(make_pair(values[i]/weights[i], weights[i]));
instead of creating into a temporary variable x . However the same issue still stands.
Any help in the right direction would be greatly appreciated.
If there is any further clarification that I can give please ask me.
If you'd like to see for some values below is a snippet which can be compiled
I use input
3 50
60 20
100 50
120 30
#include <iostream>
#include <vector>
#include <algorithm>
using namespace std;
double get_optimal_value(int capacity, vector<int> weights, vector<int> values) {
double value = 0.0;
int n = weights.size();
vector<pair<double, int>> valuePerWeight(n);
pair<double,int> x;
for(int i = 0; i < n; i++){
double v = values[i]/weights[i];
cout << v << ' '<< weights[i] << '\n';
x = make_pair(values[i]/weights[i], weights[i]);
cout << x.first << ' ' << x.second << '\n';
valuePerWeight.push_back(x);
cout << valuePerWeight[i].first << ' ' << valuePerWeight[i].second << '\n';
}
for(int i = 0; i < n; i++){
cout << valuePerWeight[i].first;
cout << valuePerWeight[i].second;
cout << '\n';
}
sort(valuePerWeight.begin(), valuePerWeight.end());
for(int i = 0; i < n && capacity > 0; i++){
int amount = min(capacity, valuePerWeight[i].second);
value += valuePerWeight[i].first * amount;
capacity -= amount;
}
// for(auto vp: valuePerWeight){
// cout << vp.first << vp.second;
// cout << '\n';
// }
return value;
}
int main() {
int n;
int capacity;
std::cin >> n >> capacity;
vector<int> values(n);
vector<int> weights(n);
for (int i = 0; i < n; i++) {
std::cin >> values[i] >> weights[i];
}
double optimal_value = get_optimal_value(capacity, weights, values);
std::cout.precision(10);
std::cout << optimal_value << std::endl;
return 0;
}
The confusion here is due to the behavior of the constructor you use
vector<pair<double, int>> valuePerWeight(n);
This actually fills the vector with n default constructed pairs, which as you may surmise, are (0, 0). When you push_back, you push to the end of these, so you a totally get 2n pairs.
.reserve does something close to what you expected, not actually filling the vector, but is likely not needed for something not bottle-necking on vector resizing.
Short story, omit the (n) to just construct an empty vector.
Three more suggestions: accept the vectors as const& to save a copy, and look at emplace_back instead of making a pair yourself and pushing it. That's what it's meant for. Also, note the comment by churill - dividing two integers will result in integer division regardless of where you are assigning the result. Static cast one of them to a float or double (or multiply by 1.0 at the start) to ensure floating point division.

Program in C++ that takes 3 numbers and send them to a function and then calculate the average function of these 3 numbers

Program in C++ that takes 3 numbers and send them to a function and then calculate the average function of these 3 numbers.
I know how to do that without using a function ,for example for any n numbers I have the following program:
#include<stdio.h>
int main()
{
int n, i;
float sum = 0, x;
printf("Enter number of elements: ");
scanf("%d", &n);
printf("\n\n\nEnter %d elements\n\n", n);
for(i = 0; i < n; i++)
{
scanf("%f", &x);
sum += x;
}
printf("\n\n\nAverage of the entered numbers is = %f", (sum/n));
return 0;
}
Or this one which do that using arrays:
#include <iostream>
using namespace std;
int main()
{
int n, i;
float num[100], sum=0.0, average;
cout << "Enter the numbers of data: ";
cin >> n;
while (n > 100 || n <= 0)
{
cout << "Error! number should in range of (1 to 100)." << endl;
cout << "Enter the number again: ";
cin >> n;
}
for(i = 0; i < n; ++i)
{
cout << i + 1 << ". Enter number: ";
cin >> num[i];
sum += num[i];
}
average = sum / n;
cout << "Average = " << average;
return 0;
}
But is it possible to use functions?if yes then how? thank you so much for helping.
As an alternative to using fundamental types to store your values C++ provides std::vector to handle numeric storage (with automatic memory management) instead of plain old arrays, and it provides many tools, like std::accumulate. Using what C++ provides can substantially reduce your function to:
double avg (std::vector<int>& i)
{
/* return sum of elements divided by the number of elements */
return std::accumulate (i.begin(), i.end(), 0) / static_cast<double>(i.size());
}
In fact a complete example can require only a dozen or so additional lines, e.g.
#include <iostream>
#include <vector>
#include <numeric>
double avg (std::vector<int>& i)
{
/* return sum of elements divided by the number of elements */
return std::accumulate (i.begin(), i.end(), 0) / static_cast<double>(i.size());
}
int main (void) {
int n; /* temporary integer */
std::vector<int> v {}; /* vector of int */
while (std::cin >> n) /* while good integer read */
v.push_back(n); /* add to vector */
std::cout << "\naverage: " << avg(v) << '\n'; /* output result */
}
Above, input is taken from stdin and it will handle as many integers as you would like to enter (or redirect from a file as input). The std::accumulate simply sums the stored integers in the vector and then to complete the average, you simply divide by the number of elements (with a cast to double to prevent integer-division).
Example Use/Output
$ ./bin/accumulate_vect
10
20
34
done
average: 21.3333
(note: you can enter any non-integer (or manual EOF) to end input of values, "done" was simply used above, but it could just as well be 'q' or "gorilla" -- any non-integer)
It is good to work both with plain-old array (because there is a lot of legacy code out there that uses them), but equally good to know that new code written can take advantage of the nice containers and numeric routines C++ now provides (and has for a decade or so).
So, I created two options for you, one use vector and that's really comfortable because you can find out the size with a function-member and the other with array
#include <iostream>
#include <vector>
float average(std::vector<int> vec)
{
float sum = 0;
for (int i = 0; i < vec.size(); ++i)
{
sum += vec[i];
}
sum /= vec.size();
return sum;
}
float average(int arr[],const int n)
{
float sum = 0;
for (int i = 0; i < n; ++i)
{
sum += arr[i];
}
sum /= n;
return sum;
}
int main() {
std::vector<int> vec = { 1,2,3,4,5,6,99};
int arr[7] = { 1,2,3,4,5,6,99 };
std::cout << average(vec) << " " << average(arr, 7);
}
This is an example meant to give you an idea about what needs to be done. You can do this the following way:
// we pass an array "a" that has N elements
double average(int a[], const int N)
{
int sum = 0;
// we go through each element and we sum them up
for(int i = 0; i < N; ++i)
{
sum+=a[i];
}
// we divide the sum by the number of elements
// but we first have to multiply the number of elements by 1.0
// in order to prevent integer division from happening
return sum/(N*1.0);
}
int main()
{
const int N = 3;
int a[N];
cin >> a[0] >> a[1] >> a[2];
cout << average(a, N) << endl;
return 0;
}
how to do that without using a function
Quite simple. Just put your code in a function, let's call it calculateAverage and return the average value from it. What should this function take as input?
The list of numbers (array of numbers)
Total numbers (n)
So let's first get the input from the user and put it into the array, you have already done it:
for(int i = 0; i < n; ++i)
{
cout << i + 1 << ". Enter number: ";
cin >> num[i];
}
Now, lets make a small function i.e., calculateAverage():
int calculateAverage(int numbers[], int total)
{
int sum = 0; // always initialize your variables
for(int i = 0; i < total; ++i)
{
sum += numbers[i];
}
const int average = sum / total; // it is constant and should never change
// so we qualify it as 'const'
//return this value
return average
}
There are a few important points to note here.
When you pass an array into a function, you will loose size information i.e, how many elements it contains or it can contain. This is because it decays into a pointer. So how do we fix this? There are a couple of ways,
pass the size information in the function, like we passed total
Use an std::vector (when you don't know how many elements the user will enter). std::vector is a dynamic array, it will grow as required. If you know the number of elements beforehand, you can use std::array
A few problems with your code:
using namespace std;
Don't do this. Instead if you want something out of std, for e.g., cout you can do:
using std::cout
using std::cin
...
or you can just write std::cout everytime.
int n, i;
float num[100], sum=0.0, average;
Always initialize your variables before you use them. If you don't know the value they should be initialized to, just default initialize using {};
int n{}, i{};
float num[100]{}, sum=0.0, average{};
It is not mandatory, but good practice to declare variables on separate lines. This makes your code more readable.

How many numbers higher than average [C++]

I filled an array with 30 random numbers and calculated average. I want to display how many numbers are higher than the average. I tried making a function "aboveAverage" and check if the numbers are higher than the average and than just increase the count "num_over_average++". The problem is I don't know how to pass a value "avg" from function to another function.
#include <iostream>
#include <ctime>
using namespace std;
const int n = 30;
void fillArray(int age[], int n) {
srand(time(NULL));
for (int index = 0; index < n; index++) {
age[index] = (rand() % 81) + 8;
}
}
void printArray(int age[], int n) {
for (int index = 0; index < n; index++) {
cout << age[index] << endl;
}
}
double printAverage(int age[], int n) {
double sum;
double avg = 0.0;
for (int i = 0; i < n; i++) {
sum = sum + age[i];
}
avg = ((double) sum) / n;
cout << avg << endl;
return avg;
}
void aboveAverage(int age[], int n) {
double avg;
int num_over_average = 0;
for(int i = 0; i < n; i++){
if(age[i] > avg) {
num_over_average++;
}
}
cout<<num_over_average;
}
int main(int argc, char *argv[]) {
int age[n];
fillArray(age, n);
cout << "array: " << endl;
printArray(age, n);
cout << endl;
aboveAverage(age, n);
//example: Days above average: 16
}
This should be a comment, but I don't have enough reps :(
Change aboveAverage to void aboveAverage(int age[], int n, double avg)
Return avg from printAverage function
Change the last part of your main code to
double avg;
avg = printAverage(age, n);
aboveAverage(age, n, avg);
Hope this helps!
You have two solutions using your code:
Either you call printAverage() to initialise avg in aboveAverage() :
void aboveAverage(int age[], int n) {
double avg = printAverage();
...
}
Or you pass the average at parameter of aboveAverage() after having computed it with printAverage() :
void aboveAverage(int age[], int n, double avg) {
...
}
If you use the standard library you can do that with two lines of code:
double average = std::accumulate(std::begin(age), std::end(age), 0.0) / std::size(age);
int above_average = std::count_if(std::begin(age), std::end(age),
[average](double value) { return average < value; });
Okay, you might count that as three lines.
One major advantage of this approach over the code in the question is that you can change the container type to, say, vector<double> without having to change any of this code.
Well is pretty simple but dependent on your situation, I'll elaborate.
I'm the case when it's part of a bigger function (do-somthing())
You could calculate the average value like so and pass it to your "aboveAverage" function and print it:
double n_average = printAverage(nArr_ages, n_agesArraySize);
aboveAverage(nArr_ages, n_agesArraySize, n_averag);
Myself would probably rewrite the printAverage function as two functions, one that returns the average value based on the array and another that prints it not both at once because it violates the SOLID principals of a single responsibility and that a function name should reflect exactly what it does, in this case maybe calculateAverage or getAverageAge or any other appropriate name will do (try and name your functions like the english language so your code will be read like a song.
For example:
const size_t n = 30;
double calculateAverage(int nArr_ages[], int n_agesArraySize) {
double sum = 0.0;
double avg = 0.0;
for (int indexInArray = 0; indexInArray < n_agesArraySize; indexInArray++) {
sum = sum + age[indexInArray];
}
average = ((double) sum) / n_agesArraySize;
return average;
}
int aboveAverageCells(int ages[], int n_agesArraySize ) {
double average = calculateAverage(ages, n);
int num_over_average = 0;
for(int indexInArray = 0; indexInArray < n_agesArraySize; indexInArray++) {
if(ages[indexInArray] > avg) {
num_over_average++;
}
}
return num_over_average;
}
Now just call them in order, save the returned values to local variables in the main function and print using cout also locally in main.
As a side note next time maybe choose different names for the const and the local functions variable for the array size.

c++ Problems with operator overloading [duplicate]

This question already has answers here:
What are the basic rules and idioms for operator overloading?
(8 answers)
Closed 4 years ago.
My assignment is to use operator overloading to
create a random number array
get lowest number
get highest number
get average
get total and
get standard deviation.
It is just a mess. Here is my code:
#ifndef ASSIGNMENT6_HEAD6_H
#define ASSIGNMENT6_HEAD6_H
#include <iostream>
using namespace std;
class Analyzer {
//Private Member
private:
int numbers;
//Public Member
public:
Analyzer();//default constructor
~Analyzer();//destructor
Analyzer operator+(const Analyzer &a) const;
friend numbers operator+();
};//end of class
#endif //ASSIGNMENT6_HEAD6_H
//Class math with overloading operator and friends
#include "head6.h"
#include <cmath>
#include <iostream>
#include <string>
#include <iomanip>
#include <vector>
using namespace std;
vector<int> numbers;
int min = numbers[0];
int max = numbers[0];
int sizeofArray;
Analyzer::Analyzer() {
}
int getLowest(const int[], int);
//Random number member
void randNumbers(int sizeofArray, int* numbers[]) {
for (int index = 0; index < sizeofArray; index++)
{
numbers[index] = (numbers() % 499) + 100;
}return;
}
//Setters
int lowest = getLowest(numbers, sizeofArray);
int highest = getHighest(numbers, sizeofArray);
float total = getTotal(numbers);
double average = getAverage(total, sizeofArray);
//Lowest number
void getLowest(const int numbers[], int sizeofArray) {
for (int i = 0; i < sizeofArray; i++) {
if (min > numbers[i]) {
min = numbers[i];
min = lowest;
}
}
return;
}
//Highest number
void getHighest(const int numbers[], int sizeofArray) {
for (int i = 0; i < sizeofArray; i++) {
if (max > numbers[i]) {
max = numbers[i];
max = lowest;
}
}
return;
}
//Total
float getTotal(const int numbers) {
total = sum(numbers[]);
return total;
}
//Average
double getAverage(const float total, int sizeofArray) {
double average = total / sizeofArray;
return average;
}
//standard deviation
float getStandardDeviation(int sizeofArray, float numbers[])const
{
float deviation1;
for (int i = 0; i < sizeofArray; i++)
sum = (mean - numbers[i]) * (mean - numbers[i]);
deviation1 = sqrt(sum / sizeofArray - 1);
float deviation = deviation1;
return deviation;
}
string a() {
stringstream sout;
sout << "STATISTICAL ANALYSIS OF RANDOMLY GENERATED NUMBERS" << endl;
sout << "====================================================" << endl;
sout << left << "Lowest Number:" << left << getLowest() << endl;
sout << left << "Highest Number:" << left << getHighest() << endl;
sout << left << "Numbers Total:" << left << getTotal() << endl;
sout << left << "Numbers Averge:" << left << getAverage() << endl;
sout << left << "Numbers of Standard Deviation:" << left <<
getStandardDeviation() << endl;
return sout.a();
}
int ​​main()
{
Analyzer a;
a + 100;
cout << a;
return 0;
}
Thank you for any assistance.
Your assignment is to use operator overloading to solve the issues - but you actually don't do so anywhere (apart from the operator+ for your Analyzer class – which is meaningless, though).
Reading your lines, I'd rather assume that you're supposed to write separate classes for each task:
class Minimum
{
std::vector<int> const& values
public:
Minimum(std::vector<int> const& values) : values(values) { }
// calculates minimum / lowest value from member:
int operator()();
};
class Maximum
{
public:
//Maximum(); not needed in this variant
// calculates maximum from parameter
int operator()(std::vector<int> const& values);
};
void test()
{
std::vector<int> values({10, 12, 7});
int min = Minimum(values)();
int max = Maximum()(values);
}
These are two different patterns, for consistency, you should select one and implement all classes alike. In first approach, you can access the vector from any member function without having to pass it around as parameter, in second approach, you can re-use one and the same object to calculate the value on several different vectors (you could still maintain a pointer to the vector to avoid passing it around via parameters...).
Coming back to your original code, unfortunately it is full of errors
vector<int> numbers;
int min = numbers[0]; // vector is yet empty! undefined behaviour!
int max = numbers[0];
Actually, you might want not to use globals at all, see later...
//int sizeofArray; // use numbers.size() instead!
// not an error, but questionable: you have a std::vector already, why do you
// fall back to C-style raw arrays?
void randNumbers(int sizeofArray, int* numbers[])
// ^ array of pointers???
{
for (int index = 0; index < sizeofArray; index++)
{
numbers[index] = (numbers() % 499) + 100;
// you certainly intended to use rand function
}
// return; // just plain obsolete
}
// vector variant:
void randNumbers(unsigned int numberOfValues, std::vector<int>& destination)
// ^ not how many numbers ARE in,
// but how many SHALL be inserted
{
// assuming we want to re-use this function and guarantee that EXACTLY
// 'numberOfValues' values are contained:
destination.clear(); // there might have been some values in already...
// assure sufficently internal memory pre-allocated to prevent
// multiple re-allocations during filling the vector:
destination.reserve(numberOfValues);
while(numberOfValues--)
{
numbers.push_back(rand() * 500 / RAND_MAX + 100);
// modulus is unprecise; this calculation will give you better
// distribution
// however, rather prefer modern C++ random number generators!
// IF you use rand: assure that you call srand, too, but exactly ONCE,
// best right when entering main function
}
}
// C++ random number generator:
void randNumbers(unsigned int numberOfValues, std::vector<int>& destination)
{
static std::uniform_int_distribution<> d(100, 599);
static std::mt19937 g;
destination.clear();
destination.reserve(numberOfValues);
while(numberOfValues--)
{
numbers.push_back(d(g));
}
}
Now you have contradicting function declarations:
int getLowest(const int[], int);
void getLowest(const int numbers[], int sizeofArray) { /* ... */ }
int lowest = getLowest(numbers, sizeofArray);
// again: the vector is yet empty!
// so you certainly won't get the result desired
// however, this won't compile at all: numbers is a std::vector,
// but parameter type is array, so you need:
int lowest = getLowest(numbers.data(), numbers.size());
// ^ replaced the redundant global as well
// move this into your main function AFTER having filled the vector!
// picking int as return value:
int getLowest(const int numbers[], unsigned int sizeofArray)
{
// you'd now have to initialize the global first; better, though:
// return a local variable:
// this assumes that there is at least one element in! check before usage
// and decide what would be the appropriate error handling if the vector
// is empty (return 0? return INT_MIN? throw an execption?)
int min = numbers[0];
for (int i = 1; i < sizeofArray; i++)
{
if (min > numbers[i])
{
min = numbers[i];
// min = lowest; // don't overwrite the minimum again!
}
}
// returning at end of void function is obsolete, don't do that explicitly
// well, with int as return value, as is NOW, you NEED to return:
return min;
}
Maximum analogously, be aware that you did not change the comparison from > to <! Be aware that there are already std::min_element, std::max_element and std::minmax_element which do the same (if not prohibited by the assignment, you should rather use these instead of re-inventing the wheel).
// prefere double! float (on typical machines at least) has same size as int
// and it is quite likely that you will lose precision due to rounding; I
// personally would rather use int64_t instead, so you won't run into rounding
// issues even with double and you'd need quite a large amount of summands
// before overflow can occur...
float getTotal(const int numbers) // just one single number???
{
total = sum(numbers[]);
// index operator cannot be applied on a single int; additionally, you need
// to provide an argument; where is 'sum' function defined at all???
return total;
}
// prefer double again
double getStandardDeviation(int sizeofArray, float numbers[]) // const
// (free standing functions cannot be const)
{
// mean isn't declared/defined anywhere (average instead?)!
// and you need to declare and initialize the sum appropriately:
double sum = 0.0;
float deviation1;
for (int i = 0; i < sizeofArray; i++)
sum += (mean - numbers[i]) * (mean - numbers[i]);
// ^ you need to add, if you want to build sum
// why two variables, even both of same type???
deviation1 = sqrt(sum / sizeofArray - 1);
float deviation = deviation1;
return deviation;
// simplest: drop both deviation and deviation 1 and just do:
return sqrt(sum / sizeofArray - 1);
}
Finally: I don't think that you'd use the resulting string (below) for anything else than printing out to console again, so I'd output to std::cout directly (naming the function 'print'); if at all, I'd provide a std::ostream as parameter to be more flexible:
void print(std::ostream& sout)
{
sout << "STATISTICAL ANALYSIS OF RANDOMLY GENERATED NUMBERS" << endl;
sout << "====================================================" << endl;
sout << left << "Lowest Number:" << left << getLowest() << endl;
sout << left << "Highest Number:" << left << getHighest() << endl;
sout << left << "Numbers Total:" << left << getTotal() << endl;
sout << left << "Numbers Averge:" << left << getAverage() << endl;
sout << left << "Numbers of Standard Deviation:" << left
<< getStandardDeviation() << endl;
}
Now you could pass std::cout to, a std::ostringstream object or even write to file via a std::ofstream...
int ​​main()
{
Analyzer a, b, c; // b, c added by me for illustration only
a + 100;
// the operator accepts another Analyzer object, so you could do
c = a + b;
cout << a; // there's no operator<< overload for Analyzer class
// it is HERE where you'd call all your getXZY functions!
return 0;
}
You are passing a pointer to an array of integers:
void randNumbers(int sizeofArray, int* numbers[])
where you really just want to pass numbers as an array. And since all arrays degrade to pointers when passed as a parameter, your function is simply this:
void randNumbers(int sizeofArray, int* numbers) {
for(int index = 0; index < sizeofArray; index++) {
numbers[index]= (rand() % 499) + 100;
};
}
The result is that the items in numbers will be integers in the range of [100..599] inclusive.

Converting Array of type float to doubles

I really need help on learning how to convert arrays of different types to doubles (short, long, float). I'm not really sure how to ask the question any better. This is for an assignment for school. I understand that the assignment isn't complete, I just need to learn to do this before I continue to make arrays for short and long types.
Assignment Description:
We are going to expand program to account for different primitives. This implementation will implement all 8 functions described in program 2 as templates. To show this works, the main function will declare 4 different arrays that contain 10 values. The different arrays will be declared as shorts, longs, floats, and doubles. Each array will be filled with random values from a random-number generator. The array will be printed, then each of the 8 functions will be called and the results printed to the user. In order to provide a container, each of the functions will be part of a class called “MathHelper” that has all of the functions declared with a public access modifier and a static modifier.
MathHelper.h
#pragma once
class MathHelper
{
public:
static double calculateSum(const double numbers[], const int& count);
static double calculateAverage(const double numbers[], const int& count);
static int highestNum(const double numbers[], const int& count);
//int lowestNum(const int numbers[], const int& count);
//int numRange(const int numbers[], const int& count);
//double standardDeviation(const int numbers[], const int& count);
//int smallestFactorial(const int numbers[], const int& count);
};
MathHelper.cpp
#include "MathHelper.h"
MathHelper::MathHelper()
{
}
double MathHelper::calculateSum(const double numbers[], const int& count)
{
if (count <= 0)
return 0;
double total = 0;
for (int i = 0; i < count; i++)
total += numbers[i];
return total;
}
double MathHelper::calculateAverage(const double numbers[], const int& count)
{
if (count <= 0)
return 0;
return static_cast<double>(calculateSum(numbers, count)) / count;
}
int MathHelper::highestNum(const double numbers[], const int& count)
{
if (count <= 0)
return 0;
int highest = numbers[0];
for (int i = 1; i < count; ++i)
if (highest < numbers[i])
highest = numbers[i];
return highest;
}
MathHelper::~MathHelper()
{
}
Program4.cpp
// Program4Fix.cpp : Defines the entry point for the console application.
//
#include "stdafx.h"
#include "MathHelper.h"
#include <iostream>
#include <cmath>
#include <ctime>
#include <iomanip>
int main()
{
const int size = 10;
double* myDoubles = new double[size];
float* myFloats = new double[size];
srand((unsigned)time(NULL));
// double fill
std::cout << std::endl;
std::cout << "Double Array: \n";
for (int i = 0; i < size; i++)
{
*(myDoubles + i) = rand() / double(RAND_MAX)*50.f + 1.f;
std::cout << i << ": " << std::setprecision(4) << *(myDoubles + i) << std::endl;
}
std::cout << std::setprecision(5) << "The sum of the numbers is: " << MathHelper::calculateSum(myDoubles, size) << "\n";
std::cout << std::setprecision(5) << "The average of the numbers is: " << MathHelper::calculateAverage(myDoubles, size) << "\n";
// long fill
std::cout << "Float Array: \n";
for (int i = 0; i < size; i++)
{
*(myFloats + i) = rand() / float(RAND_MAX)*50.f + 1.f;
std::cout << i << ": " << std::setprecision(4) << *(myFloats + i) << std::endl;
}
std::cout << std::setprecision(5) << "The sum of the numbers is: " << MathHelper::calculateSum(myFloats, size) << "\n";
std::cout << std::setprecision(5) << "The average of the numbers is: " << MathHelper::calculateAverage(myFloats, size) << "\n";
return 0;
}
I guess my real question is, is there anyway to use a value of type double* to initialize an entity of type float*?
const int size = 10;
double* myDoubles = new double[size]; // this works
float* myFloats = new double[size]; // this doesn't work, is there a way to do this similar to the one above?
Since you are asking about C++, don't use implicit conversion
double d = 1.5;
int i = d;
Also don't use c-style casting:
double d = 1.5;
int i = (int)d;
Make use of proper casting
int i = static_cast<int>(d);
You can read up on why, there are many reasons why to cast in C++.
For converting the array, you need to create a new array and then iterate over the existing one, convert one by one and then assign them to the new one.
For C++11 you can possibly use the std::transform() function.
I guess what you should do is generalize the functions in MathHelper to template functions which can be used for other types than double. I would get a decent C++ book and read about template functions, e.g. in A Tour of C++ or Programming -- Principles and Practice Using C++. You can get the first four chapters for the Tour of C++ from isocpp.org, and the second chapter introduces templates.
In the end, you should have code that looks like
class MathHelper
{
public:
template<typename T> static double calculateSum(const T numbers[], const int& count);
};
As a general remark, the posted code looks very C-ish meaning that it uses C-constructs where C++ has better alternatives, e.g. manually managed arrays instead of std::vector. You should avoid this.
Converting to double from float, int, or long is as simple as just assigning the source variable to a variable declared double.
For example:
int a = 1
long b = 2;
float c = 3.0f;
double result;
result = a;
result = b;
result = c;
In the 3 last statements, the values will be converted to doubles for you.
You can also convert the other way by casting.
const int size = 10;
double* myDoubles = new double[size];
float* myFloats = new float[size];
InitializeArray(myDoubles); // You'll have to start with some values
for(int i = 0; size > i; ++i)
{
myFloats[i] = (float) myDoubles[i];
}