библиотека округления делений int?

Кто-нибудь знает библиотеку C или C ++ с открытым исходным кодом с функциями, реализующими каждый режим целочисленного деления? Возможные варианты поведения (для положительного результата):

round_down, round_up,
round_to_nearest_with_ties_rounding_up,
round_to_nearest_with_ties_rounding_down,
round_to_nearest_with_ties_rounding_to_even,
round_to_nearest_with_ties_rounding_to_odd

причем каждый (кроме округления до четного и округления до нечетного) имеет два варианта

// (round relative to 0; -divide(-x, y) == divide(x, y))
negative_mirrors_positive,
// (round relative to -Infinity; divide(x + C*y, y) == divide(x, y) + C)
negative_continuous_with_positive

.

Я знаю, как написать это, но наверняка кто-то уже сделал это?

В качестве примера, если мы предположим (что является обычным и обязательным в C ++ 11), что встроенное знаковое целочисленное деление округляется до нуля и что встроенный модуль согласуется с этим, то

int divide_rounding_up_with_negative_mirroring_positive(int dividend, int divisor) {
// div+mod is often a single machine instruction.
const int quotient = dividend / divisor;
const int remainder = dividend % divisor;
// this ?:'s condition equals whether quotient is positive,
// but we compute it without depending on quotient for speed
// (instruction-level parallelism with the divide).
const int adjustment = (((dividend < 0) == (divisor < 0)) ? 1 : -1);
if(remainder != 0) {
return quotient + adjustment;
}
else {
return quotient;
}
}

Бонусные баллы: работа для нескольких типов аргументов; быстро; при желании также вернуть модуль; не переполняйте значения аргументов (кроме деления на ноль и MIN_INT / -1, конечно).

Если я не найду такую ​​библиотеку, я напишу ее на C ++ 11, опубликую и сошлюсь на нее в ответе здесь.

2

Решение

Итак, я написал что-то. Реализация обычно представляет собой некрасивый шаблон и побитовый код, но работает хорошо. Использование:

divide(dividend, divisor, rounding_strategy<...>())

где rounding_strategy<round_up, negative_mirrors_positive> пример стратегии; см список вариантов в моем вопросе или в исходном коде. https://github.com/idupree/Lasercake/blob/ee2ce96d33cad10d376c6c5feb34805ab44862ac/data_structures/numbers.hpp#L80

зависит только от C ++ 11 [*], причем модульные тесты (с использованием инфраструктуры Boost Test) начинаются с https://github.com/idupree/Lasercake/blob/ee2ce96d33cad10d376c6c5feb34805ab44862ac/tests/misc_utils_tests.cpp#L38

Он полиморфен, имеет приличную скорость и не переполняется, но в настоящее время не возвращает модуль.

[*] (и для boost :: make_signed и boost :: enable_if_c, которые тривиально заменить на std :: make_signed и std :: enable_if, а также на наш caller_error_if (), который можно заменить assert () или if (. .) {throw ..} или удалено. Вы можете игнорировать и удалять оставшуюся часть файла, если вас не интересуют другие вещи.)

Код каждого div_impl можно адаптировать к C, заменив каждый T, например, на. int и T (CONSTANT) с CONSTANT. В случае варианта round_to_nearest_ * вы бы хотели сделать тип округления аргументом времени выполнения или создать шесть копий кода (по одной для каждого отдельного варианта округления, который он обрабатывает). Код полагается на округление ‘/’ до нуля, что является общим и также определяется C11 (стандартный проект N1570 6.5.5.6), а также C ++ 11. Для совместимости с C89 / C ++ 98 он может использовать stdlib.h div () / ldiv (), который гарантированно округляется до нуля (см. http://www.linuxmanpages.com/man3/div.3.php , http://en.cppreference.com/w/cpp/numeric/math/div )

1

Другие решения

Других решений пока нет …

По вопросам рекламы [email protected]