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
|
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 $^
|
$(CXX) $(CXXFLAGS) -o GeothmeticMeandian $^
|
||||||
|
|
||||||
.PHONY:
|
.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) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in a new issue