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.
Помогите? Благодарю.
документы сказать
Преобразования также допускаются:
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";
}
Других решений пока нет …