Working C++ impl

This commit is contained in:
Stephen Seo 2021-05-01 22:31:59 +09:00
parent 42ef4e9bb3
commit 5e8596dd8d
8 changed files with 177 additions and 1 deletions

View file

@ -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:

View 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;
}

View file

@ -0,0 +1,6 @@
#ifndef GEOMETRIC_MEAN_HPP
#define GEOMETRIC_MEAN_HPP
double geometric_mean(double a, double b);
#endif

View 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];
}

View 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
View 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
View file

@ -0,0 +1,6 @@
#ifndef HELPERS_HPP
#define HELPERS_HPP
bool floating_point_similar(double a, double b, unsigned char decimal = 5);
#endif

View file

@ -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;
}