Раунд буст :: multiprecision :: mpq_rational до ближайшего целого

Каков наилучший способ округлить boost :: multiprecision :: mpq_rational до ближайшего целого числа?

Уродливое решение:

#include <boost/multiprecision/gmp.hpp>
using namespace boost::multiprecision;

inline int round_to_int(mpq_rational v)
{
mpz_int vf_mpz = numerator(v) / denominator(v);
mpz_t z;
mpz_init(z);
mpz_set(z, vf_mpz.backend().data());
int vf = mpz_get_si(z);
if (v - vf_mpz < vf_mpz + 1 - v) return vf;
else return vf + 1;
}

Есть идеи получше?

1

Решение

По крайней мере исправьте это для отрицательных чисел, поскольку прямо сейчас -13/7 округлилось бы до -1 (когда -2 намного ближе).

Кроме того, поскольку диапазон в конечном итоге должен отображаться на intпросто:

template <typename rational>
inline int round_to_int(rational v)
{
v = v + typename rational::number(v.sign()) / 2;
return v.template convert_to<int>();
}

Это приводит к более разумным результатам, для отрицательных чисел: посмотрите это Жить на Колиру

-2   -2.00      -2
-13/7    -1.86      -2
-12/7    -1.71      -2
-11/7    -1.57      -2
-10/7    -1.43      -1
-9/7     -1.29      -1
-8/7     -1.14      -1
-1   -1.00      -1
-2   -2.00      -2
-13/7    -1.86      -2
-12/7    -1.71      -2
-11/7    -1.57      -2
-10/7    -1.43      -1
-9/7     -1.29      -1
-8/7     -1.14      -1
-1   -1.00      -1
-6/7     -0.86      -1
-5/7     -0.71      -1
-4/7     -0.57      -1
-3/7     -0.43       0
-2/7     -0.29       0
-1/7     -0.14       0
0     0.00       0
1/7   0.14       0
2/7   0.29       0
3/7   0.43       0
4/7   0.57       1
5/7   0.71       1
6/7   0.86       1
1     1.00       1
8/7   1.14       1
9/7   1.29       1
10/7      1.43       1
11/7      1.57       2
12/7      1.71       2
13/7      1.86       2
2     2.00       2
----------------------
-2   -2.00      -2
-3/2     -1.50      -2
-1   -1.00      -1
-1/2     -0.50      -1
0     0.00       0
1/2   0.50       1
1     1.00       1
3/2   1.50       2
2     2.00       2

Полный код:

#include <boost/multiprecision/mpfr.hpp>
#include <boost/multiprecision/number.hpp>
#include <vector>

using boost::multiprecision::mpq_rational;

template <typename rational>
inline int round_to_int(rational v)
{
v = v + typename rational::number(v.sign()) / 2;
return v.template convert_to<int>();
}

int main()
{
auto show = [](mpq_rational a) {
std::cout << std::right << a << "\t" << std::setw(6) << (double) a << "\t" << std::right << std::setw(6) << round_to_int(a) << '\n';
};
std::cout << std::fixed << std::setprecision(2);

for (mpq_rational r(-2); r<=2; r = (r*7+1)/7)
show(r);
std::cout << "----------------------\n";
for (mpq_rational r(-2); r<=2; r = (r*2+1)/2)
show(r);
}
3

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


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