Working C++ impl
This commit is contained in:
parent
42ef4e9bb3
commit
5e8596dd8d
8 changed files with 177 additions and 1 deletions
|
@ -8,7 +8,7 @@ endif
|
|||
|
||||
all: GeothmeticMeandian
|
||||
|
||||
GeothmeticMeandian: src/main.o
|
||||
GeothmeticMeandian: src/main.o src/geometric_mean.o src/geothmetic_meandian.o src/helpers.o
|
||||
$(CXX) $(CXXFLAGS) -o GeothmeticMeandian $^
|
||||
|
||||
.PHONY:
|
||||
|
|
21
cpp_impl/src/geometric_mean.cpp
Normal file
21
cpp_impl/src/geometric_mean.cpp
Normal file
|
@ -0,0 +1,21 @@
|
|||
#include "geometric_mean.hpp"
|
||||
|
||||
#include <cmath>
|
||||
#include <string>
|
||||
|
||||
#include "helpers.hpp"
|
||||
|
||||
double geometric_mean(double a, double b) {
|
||||
double temp_a;
|
||||
double temp_b;
|
||||
|
||||
while(!floating_point_similar(a, b, 5)) {
|
||||
temp_a = a;
|
||||
temp_b = b;
|
||||
|
||||
a = (temp_a + temp_b) / 2.0;
|
||||
b = std::sqrt(temp_a * temp_b);
|
||||
}
|
||||
|
||||
return a;
|
||||
}
|
6
cpp_impl/src/geometric_mean.hpp
Normal file
6
cpp_impl/src/geometric_mean.hpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef GEOMETRIC_MEAN_HPP
|
||||
#define GEOMETRIC_MEAN_HPP
|
||||
|
||||
double geometric_mean(double a, double b);
|
||||
|
||||
#endif
|
83
cpp_impl/src/geothmetic_meandian.cpp
Normal file
83
cpp_impl/src/geothmetic_meandian.cpp
Normal file
|
@ -0,0 +1,83 @@
|
|||
#include "geothmetic_meandian.hpp"
|
||||
|
||||
#include <array>
|
||||
#include <numeric>
|
||||
#include <cmath>
|
||||
#include <algorithm>
|
||||
|
||||
#include "helpers.hpp"
|
||||
|
||||
bool is_all_equal(const std::array<double, 3> &values) {
|
||||
// return std::all_of(values.begin(), values.end(), floating_point_similar);
|
||||
|
||||
/*
|
||||
double first = values.at(0);
|
||||
for(std::size_t i = 1; i < values.size(); ++i) {
|
||||
if(values[i] != first) {
|
||||
return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
*/
|
||||
return floating_point_similar(values[0], values[1], 5)
|
||||
&& floating_point_similar(values[1], values[2], 5);
|
||||
}
|
||||
|
||||
double geothmetic_meandian(std::vector<double> values) {
|
||||
if(values.empty()) {
|
||||
return 0.0;
|
||||
} else if(values.size() == 1) {
|
||||
return values[0];
|
||||
}
|
||||
|
||||
std::sort(values.begin(), values.end());
|
||||
|
||||
std::array<double, 3> current, temp;
|
||||
bool isFirstIteration = true;
|
||||
|
||||
do {
|
||||
if(isFirstIteration) {
|
||||
// mean
|
||||
current[0] = std::accumulate(
|
||||
values.begin(),
|
||||
values.end(),
|
||||
0.0)
|
||||
/ values.size();
|
||||
// geometric mean
|
||||
current[1] = std::accumulate(
|
||||
values.begin(),
|
||||
values.end(),
|
||||
1.0,
|
||||
[] (const auto &a, const auto &b) {
|
||||
return a * b;
|
||||
});
|
||||
current[1] = std::pow(current[1], 1.0 / (double)values.size());
|
||||
// median
|
||||
current[2] = values[values.size() / 2];
|
||||
isFirstIteration = false;
|
||||
} else {
|
||||
temp = current;
|
||||
|
||||
// mean
|
||||
current[0] = std::accumulate(
|
||||
temp.begin(),
|
||||
temp.end(),
|
||||
0.0)
|
||||
/ temp.size();
|
||||
// geometric mean
|
||||
current[1] = std::accumulate(
|
||||
temp.begin(),
|
||||
temp.end(),
|
||||
1.0,
|
||||
[] (const auto &a, const auto &b) {
|
||||
return a * b;
|
||||
});
|
||||
current[1] = std::pow(current[1], 1.0 / (double)temp.size());
|
||||
// median
|
||||
std::sort(temp.begin(), temp.end());
|
||||
current[2] = temp[temp.size() / 2];
|
||||
}
|
||||
} while(!is_all_equal(current));
|
||||
|
||||
return current[0];
|
||||
}
|
8
cpp_impl/src/geothmetic_meandian.hpp
Normal file
8
cpp_impl/src/geothmetic_meandian.hpp
Normal file
|
@ -0,0 +1,8 @@
|
|||
#ifndef GEOTHMETIC_MEANDIAN_HPP
|
||||
#define GEOTHMETIC_MEANDIAN_HPP
|
||||
|
||||
#include <vector>
|
||||
|
||||
double geothmetic_meandian(std::vector<double> values);
|
||||
|
||||
#endif
|
16
cpp_impl/src/helpers.cpp
Normal file
16
cpp_impl/src/helpers.cpp
Normal file
|
@ -0,0 +1,16 @@
|
|||
#include "helpers.hpp"
|
||||
|
||||
#include <string>
|
||||
|
||||
bool floating_point_similar(double a, double b, unsigned char decimal) {
|
||||
std::string astr = std::to_string(a);
|
||||
std::string bstr = std::to_string(b);
|
||||
|
||||
auto a_index = astr.find_last_of('.');
|
||||
astr = astr.substr(0, a_index + decimal);
|
||||
|
||||
auto b_index = bstr.find_last_of('.');
|
||||
bstr = bstr.substr(0, b_index + decimal);
|
||||
|
||||
return astr == bstr;
|
||||
}
|
6
cpp_impl/src/helpers.hpp
Normal file
6
cpp_impl/src/helpers.hpp
Normal file
|
@ -0,0 +1,6 @@
|
|||
#ifndef HELPERS_HPP
|
||||
#define HELPERS_HPP
|
||||
|
||||
bool floating_point_similar(double a, double b, unsigned char decimal = 5);
|
||||
|
||||
#endif
|
|
@ -1,3 +1,39 @@
|
|||
#include <cstdlib>
|
||||
#include <cstdio>
|
||||
|
||||
#include "geometric_mean.hpp"
|
||||
#include "geothmetic_meandian.hpp"
|
||||
|
||||
int main(int argc, char **argv) {
|
||||
--argc; ++argv;
|
||||
|
||||
std::vector<double> input;
|
||||
double temp;
|
||||
|
||||
while(argc > 0) {
|
||||
temp = std::strtod(argv[0], nullptr);
|
||||
if(temp == 0.0) {
|
||||
puts("ERROR: Failed to parse double");
|
||||
return 1;
|
||||
} else {
|
||||
input.push_back(temp);
|
||||
}
|
||||
--argc; ++argv;
|
||||
}
|
||||
|
||||
printf("Got input:\n ");
|
||||
for(double d : input) {
|
||||
printf("%f ", d);
|
||||
}
|
||||
puts("");
|
||||
|
||||
if(input.size() == 2) {
|
||||
printf("Geometric Mean of two doubles is %f\n",
|
||||
geometric_mean(input[0], input[1]));
|
||||
} else if(input.size() > 2) {
|
||||
printf("Geomethic Meandian of input is %f\n",
|
||||
geothmetic_meandian(input));
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
|
Loading…
Reference in a new issue