Unified rounding implementation
This commit is contained in:
parent
eb36ad2c93
commit
617fbac98f
@ -191,50 +191,45 @@ parse_fractional:
|
|||||||
return result.simplify();
|
return result.simplify();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace impl
|
||||||
|
{
|
||||||
|
enum class Rounding_Mode { Ceil, Floor, Round };
|
||||||
|
|
||||||
|
static Number round(Number result, Rounding_Mode rm)
|
||||||
|
{
|
||||||
|
if (result.den <= -1 || result.den >= 1) {
|
||||||
|
if (auto const r = result.num % result.den; r != 0) {
|
||||||
|
auto const sign = (result.num < 0) xor (result.den < 0) ? -1 : 1;
|
||||||
|
|
||||||
|
if (rm == Rounding_Mode::Round)
|
||||||
|
rm = r * 2 >= result.den ? Rounding_Mode::Ceil : Rounding_Mode::Floor;
|
||||||
|
|
||||||
|
if (rm == Rounding_Mode::Floor) result.num -= sign * r;
|
||||||
|
if (rm == Rounding_Mode::Ceil) result.num += sign * r;
|
||||||
|
|
||||||
|
result.num /= result.den;
|
||||||
|
result.den = 1;
|
||||||
|
} else {
|
||||||
|
result.simplify_inplace();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
Number Number::floor() const
|
Number Number::floor() const
|
||||||
{
|
{
|
||||||
auto result = *this;
|
return impl::round(*this, impl::Rounding_Mode::Floor);
|
||||||
if (den <= -1 || den >= 1) {
|
|
||||||
if (auto const r = result.num % result.den; r != 0) {
|
|
||||||
result.num += ((num < 0) xor (den < 0) ? 1 : -1) * r;
|
|
||||||
result.num /= result.den;
|
|
||||||
result.den = 1;
|
|
||||||
} else {
|
|
||||||
result.simplify_inplace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Number Number::ceil() const
|
Number Number::ceil() const
|
||||||
{
|
{
|
||||||
auto result = *this;
|
return impl::round(*this, impl::Rounding_Mode::Ceil);
|
||||||
if (den <= -1 || den >= 1) {
|
|
||||||
if (auto const r = result.num % result.den; r != 0) {
|
|
||||||
result.num += ((num < 0) xor (den < 0) ? -1 : 1) * r;
|
|
||||||
result.num /= result.den;
|
|
||||||
result.den = 1;
|
|
||||||
} else {
|
|
||||||
result.simplify_inplace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Number Number::round() const
|
Number Number::round() const
|
||||||
{
|
{
|
||||||
auto result = *this;
|
return impl::round(*this, impl::Rounding_Mode::Round);
|
||||||
if (den <= -1 || den >= 1) {
|
|
||||||
if (auto const r = result.num % result.den; r != 0) {
|
|
||||||
auto const dir = r * 2 >= result.den ? -1 : 1;
|
|
||||||
result.num += ((num < 0) xor (den < 0) ? dir : -dir) * r;
|
|
||||||
result.num /= result.den;
|
|
||||||
result.den = 1;
|
|
||||||
} else {
|
|
||||||
result.simplify_inplace();
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return result;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
Number Number::inverse() const
|
Number Number::inverse() const
|
||||||
|
Loading…
Reference in New Issue
Block a user