ошибка преобразования из boost cpp_rational в int

boost cpp_rational, по-видимому, неправильно конвертирует в int, когда числитель и знаменатель имеют много цифр.

#include <iostream>
#include <boost/multiprecision/cpp_int.hpp>

using namespace boost::multiprecision;
using namespace std;

int main() {
cpp_rational a("4561231231235/123123123123");
std::cout << "bad convert: " << a << ' '  <<
float(a) << ' ' << int(a) << ' ' <<
a.convert_to<int>() << endl;
a = (cpp_rational)"456/123";
std::cout << "good convert: " << a << ' '  <<
float(a) << ' ' << int(a) << ' ' <<
a.convert_to<int>() << endl;
}

Выход:

bad convert: 651604461605/17589017589 37.0461 -3 -3
good convert: 152/41 3.70732 3 3

Кроме того, попытки конвертировать cpp_rational в cpp_int не компилируются, например, с использованием

cpp_int b = static_cast<cpp_int> (a);
cpp_int b = a.convert_to<cpp_int>();

То, что я хочу сделать, это разделить и округлить и никогда не ошибаться даже близко к int.

Помогите? Благодарю.

1

Решение

документы сказать

Преобразования также допускаются:

d = a; // OK, widening conversion.
d = a * b;  // OK, can convert from an expression template too.

Однако преобразования, которые по своей сути являются потерями, либо объявляются явными, либо запрещаются вообще:

d = 3.14;  // Error implicit conversion from float not allowed.
d = static_cast<mp::int512_t>(3.14);  // OK explicit construction is allowed

Итак, вы видите конверсию с потерями. Демонстрация того, что преобразование будет запрещено, если вы не указали его эксплицитно:

cpp_rational a("4561231231235/123123123123");
int i   = a;        // error: cannot convert `cpp_rational` to `int` in initialization
float f = a;        // error: cannot convert `cpp_rational` to `float` in initialization
long double ld = a; // error: cannot convert `cpp_rational` to `long double` in initialization
long long   ll = a; // error: cannot convert `cpp_rational` to `long long int` in initialization

Итак, то, что вы делаете со всеми явными приведениями, говорит компилятору: «Замолчи; я знаю, что делаю». Следовательно, почему вы не получили предупреждение.

Теперь, как все исправить: сохранить разделение в области мульти-точности:

cpp_int v = numerator(a)/denominator(a);

Ваш образец исправлен: Жить на Колиру

#include <boost/multiprecision/cpp_int.hpp>
#include <iostream>

using namespace boost::multiprecision;

int main() {
cpp_rational a("4561231231235/123123123123");
cpp_int v = numerator(a)/denominator(a);
std::cout << "convert: " << v.convert_to<int>() << "\n";

a = cpp_rational("456/123");
v = numerator(a)/denominator(a);
std::cout << "convert: " << v.convert_to<int>() << "\n";
}
2

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

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

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