diff --git a/include/fiction/algorithms/simulation/sidb/energy_distribution.hpp b/include/fiction/algorithms/simulation/sidb/energy_distribution.hpp index 9fafd752d..f06427573 100644 --- a/include/fiction/algorithms/simulation/sidb/energy_distribution.hpp +++ b/include/fiction/algorithms/simulation/sidb/energy_distribution.hpp @@ -6,6 +6,7 @@ #define FICTION_ENERGY_DISTRIBUTION_HPP #include "fiction/technology/charge_distribution_surface.hpp" +#include "fiction/utils/math_utils.hpp" #include #include @@ -34,8 +35,7 @@ std::map energy_distribution(const std::vector +#include + +namespace fiction +{ + +/** + * Rounds a number to a specified number of decimal places. + * + * @tparam T the type of the number to round. + * @param number the number to round. + * @param n the number of decimal places to round to. + * @return the number rounded to n decimal places. + */ +template +T round_to_n_decimal_places(const T number, const uint64_t n) +{ + static_assert(std::is_arithmetic_v, "T is not a number type"); + const T factor = std::pow(10, n); + return std::round(number * factor) / factor; +} + +} // namespace fiction + +#endif // FICTION_MATH_UTILS_HPP diff --git a/test/utils/math_utils.cpp b/test/utils/math_utils.cpp new file mode 100644 index 000000000..3ee42f4da --- /dev/null +++ b/test/utils/math_utils.cpp @@ -0,0 +1,50 @@ +// +// Created by Jan Drewniok on 19.04.23. +// + +#include + +#include + +using namespace fiction; + +TEST_CASE("round_to_n_decimal_places should round an input number to n decimal places", "[round_to_n_decimal_places]") +{ + SECTION("int64_t") + { + CHECK(round_to_n_decimal_places(-1LL, 0) == -1LL); + CHECK(round_to_n_decimal_places(-1LL, 10) == -1LL); + CHECK(round_to_n_decimal_places(1LL, 0) == 1LL); + CHECK(round_to_n_decimal_places(1LL, 10) == 1LL); + } + + SECTION("double") + { + const double value_positive = 3.145926; + CHECK(round_to_n_decimal_places(value_positive, 0) == 3); + CHECK(round_to_n_decimal_places(value_positive, 1) == 3.1); + CHECK(round_to_n_decimal_places(value_positive, 2) == 3.15); + CHECK(round_to_n_decimal_places(value_positive, 3) == 3.146); + CHECK(round_to_n_decimal_places(value_positive, 4) == 3.1459); + CHECK(round_to_n_decimal_places(value_positive, 5) == 3.14593); + CHECK(round_to_n_decimal_places(value_positive, 6) == 3.145926); + + const double value_negative = -3.145926; + CHECK(round_to_n_decimal_places(value_negative, 0) == -3); + CHECK(round_to_n_decimal_places(value_negative, 1) == -3.1); + CHECK(round_to_n_decimal_places(value_negative, 2) == -3.15); + CHECK(round_to_n_decimal_places(value_negative, 3) == -3.146); + CHECK(round_to_n_decimal_places(value_negative, 4) == -3.1459); + CHECK(round_to_n_decimal_places(value_negative, 5) == -3.14593); + CHECK(round_to_n_decimal_places(value_negative, 6) == -3.145926); + } + + SECTION("Edge cases") + { + CHECK(round_to_n_decimal_places(1.005, 2) == 1.0); + CHECK(round_to_n_decimal_places(0.000001, 6) == 0.000001); + CHECK(round_to_n_decimal_places(0.0000001, 6) == 0); + CHECK(round_to_n_decimal_places(-0.000001, 6) == -0.000001); + CHECK(round_to_n_decimal_places(-0.0000001, 6) == 0); + } +}