Все типы чисел, основанные на<number>, имеют общие правила преобразования. В частности:
Любой тип числа может быть сконструирован (или назначен) из любого встроенного арифметического типа, если преобразование не является убыточным (например, преобразование в int):
<
cpp_dec_float_50df(0.5);// OK construction from doublecpp_inti(450);// OK constructs from signed intcpp_intj=3.14;// Error, lossy conversion.
>
Число может быть явно построено из арифметического типа, даже если преобразование является убыточным:
<
cpp_inti(3.14);// OK explicit conversioni=static_cast<cpp_int>(3.14)// OK explicit conversioni.assign(3.14);// OK, explicit assign and avoid a temporary from the cast abovei=3.14;// Error, no implicit assignment operator for lossy conversion.cpp_intj=3.14;// Error, no implicit constructor for lossy conversion.
>
A<number>может быть преобразован в любой встроенный тип посредством функции<convert_to>члена:
<
mpz_intz(2);inti=z.templateconvert_to<int>();// sets i to 2
>
Преобразования в рациональные числа из числа с плавающей точкой всегда допускаются и являются точными и неявными, если рациональное число использует неограниченный целочисленный тип. Пожалуйста, имейте в виду, что построение рационального числа из расширенного точного типа с плавающей точкой с большим диапазоном экспонентов может эффективно запустить систему из памяти, как в крайнем случае2max_exponent/ CHAR_BITSмогут потребоваться байты хранения. Однако это не представляет проблемы для встроенных типов с плавающей запятой, поскольку диапазон экспонент для них довольно ограничен.
Преобразования в числа с плавающей точкой из рациональных округляются до ближайшего (менее 0,5 ulp ошибки), если число с плавающей точкой двоично, а тип целого числа, используемый рациональным числом, не ограничен.
Дополнительные конверсии могут поддерживаться конкретными бэкэндами.
A<number>может быть преобразован в любой встроенный тип через явный оператор преобразования: эта функциональность доступна только на компиляторах, поддерживающих явный синтаксис преобразования C++11.
<
mpz_intz(2);inti=z;// Error, implicit conversion not allowed.intj=static_cast<int>(z);// OK explicit conversion.
>
Любой тип числа может бытьявнопостроен (или назначен) из<constchar*>или<std::string>:
<
// pi to 50 places from a string:cpp_dec_float_50df("3.14159265358979323846264338327950288419716939937510");// Integer type will automatically detect "0x" and "0" prefixes and parse the string accordingly:cpp_inti("0xFFFFFFFFFFFFFFFFFFFFFFFFFFFFF000000000000000");// Invalid input always results in a std::runtime_error being thrown:i=static_cast<cpp_int>("3.14");// implicit conversions from strings are not allowed:i="23";// Error, no assignment operator for implicit conversion from string// assign member function, avoids having to create a temporary via a static_cast:i.assign("23");// OK
>.
Любой тип числа будет взаимодействовать со встроенными типами в арифметических выражениях до тех пор, пока преобразования не будут потеряны:
<
// pi to 50 places from a string:cpp_dec_float_50df="3.14159265358979323846264338327950288419716939937510";// Multiply by 2 - using an integer literal here is usually more efficient// than constructing a temporary:df*=2;// You can't mix integer types with floats though:cpp_inti=2;i*=3.14;// Error, no *= operator will be found.
>
Любой тип чисел может передаваться в и из C++ iostreams:
<
cpp_dec_float_50df="3.14159265358979323846264338327950288419716939937510";// Now print at full precision:std::cout<<std::setprecision(std::numeric_limits<cpp_dec_float_50>::max_digits10)<<df<<std::endlcpp_inti=1;i<<=256;// Now print in hex format with prefix:std::cout<<std::hex<<std::showbase<<i<<std::endl;
>
Взаимопревращения между типами чисел одного и того же семейства допускаются и являются неявными преобразованиями, если не связана потеря точности, и явными, если это:
<
int128_ti128=0;int266_ti256=i128;// OK implicit widening conversioni128_t=i256;// Error, no assignment operator found, narrowing conversion is explicit.i128_t=static_cast<int128_t>(i256);// OK, explicit narrowing conversion.mpz_intz=0;mpf_floatf=z;// OK, GMP handles this conversion natively, and it's not lossy and therefore implicit.mpf_float_50f50=2;f=f50;// OK, conversion from fixed to variable precision, f will have 50 digits precision.f50=f;// Error, conversion from variable to fixed precision is potentially lossy, explicit cast required.
>
Некоторые интерконверсии между типами чисел являются полностью общими и всегда доступны, хотя конверсии всегдаявные:
<
cpp_intcppi(2);// We can always convert between numbers of the same category -// int to int, rational to rational, or float to float, so this is OK// as long as we use an explicit conversion:mpz_intz(cppi);// We can always promote from int to rational, int to float, or rational to float:cpp_rationalcppr(cppi);// OK, int to rationalcpp_dec_float_50df(cppi);// OK, int to floatdf=static_cast<cpp_dec_float_50>(cppr);// OK, explicit rational to float conversion// However narrowing and/or implicit conversions always fail:cppi=df;// Compiler error, conversion not allowed
>
Другие межконверсии могут допускаться в особых случаях, когда это позволяет бэкэнд:
<
mpf_tm;// Native GMP type.mpf_init_set_ui(m,0);// set to a value;mpf_floati(m);// copies the value of the native type.
>
Дополнительная информация о том, какие дополнительные типы поддерживают конверсии, приведена в руководстве для каждого бэкэнда. Конструктор преобразования будет неявным, если конструктор преобразования бэкэнда также неявным, и явным, если конструктор преобразования бэкэндов также явным.
Статья Constructing and Interconverting Between Number Types раздела Chapter 1. Boost.Multiprecision Tutorial может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.