Skip to content

Instantly share code, notes, and snippets.

@MoritzMaxeiner
Created March 26, 2019 20:37
Show Gist options
  • Save MoritzMaxeiner/65abe642b8f54ec11c1de09dd36c73b8 to your computer and use it in GitHub Desktop.
Save MoritzMaxeiner/65abe642b8f54ec11c1de09dd36c73b8 to your computer and use it in GitHub Desktop.
Truncated, Floored, and Euclidean integer division (C++17)
#include <iostream>
#include <tuple>
#include <type_traits>
template<typename first_type, typename second_type>
auto operator<<(std::ostream& s, std::tuple<first_type, second_type> t) -> std::ostream&
{
auto const& [first, second] = t;
return s << "(" << first << ", " << second << ")";
}
template<typename integer>
auto divide_truncated(integer a, integer b) -> std::enable_if_t<std::is_integral_v<integer>, std::tuple<integer, integer>>
{
return {a / b, a % b};
}
template<typename integer>
auto divide_floored(integer a, integer b) -> std::enable_if_t<std::is_integral_v<integer>, std::tuple<integer, integer>>
{
auto const q = integer{a / b};
auto const r = integer{a % b};
if (r && (a < 0) != (b < 0))
return {q - 1, r + b};
return {q, r};
}
template<typename integer>
auto divide_euclidian(integer a, integer b) -> std::enable_if_t<std::is_integral_v<integer>, std::tuple<integer, integer>>
{
if (a > 0) {
return divide_truncated(a, b);
} else if (b > 0) {
return divide_floored(a, b);
} else {
auto const [q, r] = divide_floored(-a, b);
return {-q, -r};
}
}
auto main(int argc, char** argv) -> int
{
if (argc != 3)
return 1;
auto const a = std::stoi(argv[1]);
auto const b = std::stoi(argv[2]);
std::cout << "truncated:\t" << divide_truncated(a, b) << std::endl;
std::cout << "floored:\t" << divide_floored(a, b) << std::endl;
std::cout << "euclidean:\t" << divide_euclidian(a, b) << std::endl;
return 0;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment