![]() |
![]() ![]() ![]() ![]() ![]() |
![]() |
ExamplesBoost , Math Toolkit 2.5.0 , Facets for Floating-Point Infinities and NaNs
|
![]() |
Note |
---|---|
Начиная с Boost 1.48, lexical_cast больше не использует струнные потоки внутри, и теперь может обрабатывать бесконечности и NaN на большинстве платформ. |
Без использования новой локации, содержащей неконечные грани, предыдущие версии<lexical_cast
>с использованием струнного потока не были переносимы (и часто терпели неудачу), если были найдены неконечные значения.
locale old_locale; locale tmp_locale(old_locale, new nonfinite_num_put<char>); locale new_locale(tmp_locale, new nonfinite_num_get<char>);
Хотя другие примеры наполняют отдельные потоки новой локализацией, для потоков, построенных внутри lexical_cast, было необходимо назначить глобальную локализацию.
locale::global(new_locale);
<lexical_cast
>Тогда работает как ожидалось, даже с бесконечностью и NaNs.
double x = boost::lexical_cast<double>("inf"); assert(x == std::numeric:limits<double>::infinity()); string s = boost::lexical_cast<string>(numeric_limits<double>::infinity()); assert(s == "inf");
![]() |
Warning |
---|---|
Если вы используете струнный поток внутри своих функций, вам все равно может потребоваться использовать глобальную локализацию для правильной обработки нефинитов. Или вам нужно наполнить свой стрингстрим подходящим набором и поставить грани. |
![]() |
Warning |
---|---|
Вы должны знать, что спецификация C++ явно не требует, чтобы ввод от десятичных цифр строк преобразовывался округлением до ближайшего представляемого двоичного значения с плавающей точкой. (В противоположность этому десятичные цифры, считываемые компилятором, например, назначением, подобным< |
См.преобразование и округлениедля получения дополнительной информации оближайших репрезентабельныхиокруглениеиИзучение двоичныхдля получения подробной информации о входе и затруднениях округления.
Большинство библиотек iostream действительно достигают желаемогоближайшего представляемого двоичного значения с плавающей точкойдля всех значений ввода. Однако одна популярная библиотека STL не совсем добивается этого для 64-битных двойников. Видишь?Десятизначный ввод строки для удвоения может быть 1 бит неправильнодля причудливых полных деталей.
Если вы ожидаете совершить кругосветное путешествие<lexical_cast
>или<serialization
>, например, архивирование и загрузку, и хотите быть абсолютно уверены, что вы всегда получите точно идентичную двоичную модель с двойным значением, вы должны использовать предлагаемый обход, который, как считается, работает на всех платформах.
Вы должны вывести все потенциально значимые десятичные цифры, установив точность потока до<std::numeric_limits<double>::max_digits10
>(или для соответствующего типа с плавающей запятой, если не двойной) и, что важно,требуют<scientific
>формата, а не<fixed
>или автоматического (по умолчанию), например:
double output_value = any value; std::stringstream s; s << setprecison(std::numeric_limits<double>::max_digits10) << scientific << output_value; s >> input_value;
Важно, чтобы одна и та же область использовалась при сохранении архива и его загрузке. В противном случае загрузка архива может выйти из строя. По умолчанию архивы сохраняются и загружаются с помощью классического C-локала с добавлением<boost::archive::codecvt_null
>граней. Обычно вам не нужно беспокоиться об этом.
Конструкторы для архивных классов, как побочный эффект, пропитывают поток такой локализацией. Однако если вы хотите использовать грани<nonfinite_num_put
>и<nonfinite_num_get
>с архивами, то вам придется управлять локализацией вручную. Это делается путем вызова архивостроителя с флагом<boost::archive::no_codecvt
>, тем самым гарантируя, что архивостроительне наполнит поток новой локацией.
Следующий код показывает, как использовать<nonfinite_num_put
>с<text_oarchive
>.
locale default_locale(locale::classic(), new boost::archive::codecvt_null<char>); locale my_locale(default_locale, new nonfinite_num_put<char>); ofstream ofs("test.txt"); ofs.imbue(my_locale); boost::archive::text_oarchive oa(ofs, no_codecvt); double x = numeric_limits<double>::infinity(); oa & x;
Этот же метод работает с<nonfinite_num_get
>и<text_iarchive
>.
Если вы используете<nonfinite_num_put
>с<trap_infinity
>и/или<trap_nan
>флагом с архивом сериализации, то вы должны установить маску исключения потока. Архивы сериализации не проверяют состояние потока.
nonfinite_facet_simple.cppдает несколько более простых демонстраций разницы между использованием классического C locale и построением C99 infinty и NaN-совместимого locale для ввода и вывода.
См.nonfinite_facet_sstream.cppдля этого примера использования с<std::stringstream
>s.
Пример того, как обеспечить реализацию представлений MSVC "legacy" "1.#INF" и "1.#QNAN" для ввода и вывода см.nonfinite_legacy.cpp.
Обработка сигналов NaN показана на../../пример/nonfinite_signaling_NaN.cpp
Пример../../example/nonfinite_loopback_ok.cppпоказывает, что обратная связь работает нормально.
Пример../../example/nonfinite_num_facet.cppпоказывает выход и повторный ввод различных конечных и неконечных значений.
Простым примером улавливания неконечного вывода являетсяnonfinite_num_facet_trap.cpp.
Яркий пример использования Boost. Архив находится по адресу../../example/nonfinite_serialization_archives.cpp.
Полная демонстрация сериализации Франсуа Могера на../../пример/nonfinite_num_facet_serialization.cpp
Статья Examples раздела Math Toolkit 2.5.0 Facets for Floating-Point Infinities and NaNs может быть полезна для разработчиков на c++ и boost.
Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.
:: Главная :: Facets for Floating-Point Infinities and NaNs ::
реклама |