Карта сайта Kansoftware
НОВОСТИУСЛУГИРЕШЕНИЯКОНТАКТЫ
Разработка программного обеспечения

std::numeric_limits<> functions

Boost , Chapter 1. Boost.Multiprecision , Numeric Limits

Boost C++ Libraries

...one of the most highly regarded and expertly designed C++ library projects in the world. Herb Sutter and Andrei Alexandrescu, C++ Coding Standards

PrevUpHomeNext
max function

Функция<std::numeric_limits<T>::max()>возвращает наибольшее конечное значение, которое может быть представлено типом T. Если же такой величины нет, то<T()>возвращается.

Для встроенных типов обычно имеется соответствующее значение MACRO TYPE_MAX, где TYPE - CHAR, INT, FLOAT и т.д.

Другие типы, в том числе те, которые предоставляются типдефом, например<INT64_T_MAX>для<int64_t>, могут обеспечивать макроопределение.

Для удовлетворения ситуаций, когда нет специализации<numeric_limits>(например, из-за того, что точность типа изменяется во время выполнения), упакованные версии этой (и других функций) предоставляются с использованием

#include <boost/math/tools/precision.hpp>
T = boost::math::tools::max_value<T>();

Конечно, они просто используют<std::numeric_limits<T>::max()>, если доступны, но в противном случае «делай что-то разумное».

lowest function

C++11:<std::numeric_limits<T>::lowest()>является

  • Для интегральных типов такая же функция<min()>.
  • Для типов с плавающей запятой, как правило, отрицательный<max()>(но зависящий от реализации).
-(std::numeric_limits<double>::max)() == std::numeric_limits<double>::lowest();
min function

Функция<std::numeric_limits<T>::min()>возвращает минимальное конечное значение, которое может быть представлено типом T.

Для встроенных типов обычно имеется соответствующее значение MACRO TYPE_MIN, где TYPE - CHAR, INT, FLOAT и т.д.

Другие типы, в том числе те, которые предоставляются типдефом, например<INT64_T_MIN>для<int64_t>, могут обеспечивать макроопределение.

Для типов с плавающей точкой он более полно определяется какминимальное положительное нормализованное значение.

<std::numeric_limits<T>::denorm_min()>для наименьшей денормализованной величины, предусмотренной

std::numeric_limits<T>::has_denorm == std::denorm_present

Для удовлетворения ситуаций, когда нет специализации<numeric_limits>(например, из-за того, что точность типа изменяется во время выполнения), упакованные версии этой (и других функций) предоставляются с использованием

#include <boost/math/tools/precision.hpp>
T = boost::math::tools::min_value<T>();

Конечно, они просто используют<std::numeric_limits<T>::min()>.

denorm_min function

Функция<std::numeric_limits<T>::denorm_min()>возвращает наименьшееденормализованное значение, при условии

std::numeric_limits<T>::has_denorm == std::denorm_present
std::cout.precision(std::numeric_limits<double>::max_digits10);
if (std::numeric_limits<double>::has_denorm == std::denorm_present)
{
  double d = std::numeric_limits<double>::denorm_min();
    std::cout << d << std::endl; //  4.9406564584124654e-324
    int exponent;
    double significand = frexp(d, &exponent);
    std::cout << "exponent = " << std::hex << exponent << std::endl; //  fffffbcf
    std::cout << "significand = " << std::hex << significand << std::endl; // 0.50000000000000000
}
else
{
  std::cout << "No denormalization. " << std::endl;
}

Экспонент эффективно уменьшается с -308 до -324 (хотя он остается закодированным как ноль и ведущие нули появляются в значении, тем самым теряя точность до тех пор, пока значение не достигнет нуля).

round_error

Функция<std::numeric_limits<T>::round_error()>возвращает максимальную ошибку (в единицахULP), которая может быть вызвана любой базовой арифметической операцией.

round_style == std::round_indeterminate;

Стиль округления неопределим во время компиляции.

Для типов с плавающей точкой, когда округление близко, только половина бита теряется при округлении и<round_error ==0.5>. В противоположность этому, когда округление приближается к нулю или плюс/минус бесконечности, мы можем освободить до одного бита от округления и<round_error ==1>.

Для целых типов округление всегда равно нулю, поэтому в худшем случае можно округлить почти один бит, так<round_error ==1>.

<round_error()>может использоваться с<std::numeric_limits<T>::epsilon()>для оценки максимальной потенциальной ошибки, вызванной округлением. Для типов с плавающей запятой<round_error()=1/2>половина эпсилона является максимальной потенциальной ошибкой.

double round_err = std::numeric_limits<double>::epsilon() // 2.2204460492503131e-016
                 * std::numeric_limits<double>::round_error(); // 1/2
std::cout << round_err << std::endl; // 1.1102230246251565e-016

Конечно, есть много случаев, когда происходит гораздо большая потеря точности, например, вызванная. Потеря значимости или ошибка отменыили очень много итераций.

epsilon

Функция<std::numeric_limits<T>::epsilon()>имеет значение только для неинтегральных типов.

Он возвращает разницу между<1.0>и следующим значением, представляемым типом T с плавающей точкой. Таким образом, это одно наименьшее изменение бита в этом значении с плавающей точкой.

Для<double><float_64t><2.2204460492503131e-016>он показывает все, возможно, значительные 17 десятичных знаков.

std::cout.precision(std::numeric_limits<double>::max_digits10);
double d = 1.;
double eps = std::numeric_limits<double>::epsilon();
double dpeps = d+eps;
std::cout << std::showpoint // Ensure all trailing zeros are shown.
  << d << "\n"           // 1.0000000000000000
  << dpeps << std::endl; // 2.2204460492503131e-016
std::cout << dpeps - d   // 1.0000000000000002
  << std::endl;

Мы можем явно увеличить на один бит, используя функцию<boost::math::float_next()>, и результат такой же, как добавление<epsilon>.

double one = 1.;
double nad = boost::math::float_next(one);
std::cout << nad << "\n"  //  1.0000000000000002
  << nad - one // 2.2204460492503131e-016
  << std::endl;

Добавление любого меньшего значения, такого как половина<epsilon>, не повлияет на это значение.

std::cout.precision(std::numeric_limits<double>::max_digits10);
double d = 1.;
double eps = std::numeric_limits<double>::epsilon();
double dpeps = d + eps/2;
std::cout << std::showpoint // Ensure all trailing zeros are shown.
  << dpeps << "\n"       // 1.0000000000000000
  << eps/2 << std::endl; // 1.1102230246251565e-016
std::cout << dpeps - d   // 0.00000000000000000
  << std::endl;

Таким образом, эта ошибка отмены оставляет значения равными, несмотря на добавление половины<epsilon>.

Для достижения большей переносимости по платформе и типу с плавающей запятой Boost. Математика и рост. Multiprecion предоставляет пакет функций, которые «делают что-то разумное», если стандарт<numeric_limits>недоступен. Используйте их<#include <boost/math/tools/precision.hpp>>.

Допуск может быть определен с использованием этой версии эпсилона таким образом:

RealType tolerance = boost::math::tools::epsilon<RealType>() * 2;
Tolerance for Floating-point Comparisons

<epsilon>очень полезно вычислить допуск при сравнении значений с плавающей точкой, что гораздо более сложная задача, чем принято считать.

Для получения дополнительной информации вы, вероятно, хотите (но все еще нуждаетесь) см.Что должен знать каждый компьютерный ученый об арифметике с плавающей точкой

Наивный тест сравнения абсолютной разницы между двумя значениями и допуском не дает полезных результатов, если значения слишком велики или слишком малы.

Так поднимись. Тест использует алгоритм, впервые разработанный Кнутом для надежной проверки того, достаточно ли близки значения с плавающей точкой.

Увидимся, Дональд. Э. Кнут. Искусство компьютерного программирования (vol II). Copyright 1998 Addison-Wesley Longman, Inc., 0-201-89684-2. Addison-Wesley Professional; 3-е издание.

Смотрите также:

Альберто Сквассия, Сравнение поплавков

Альберто Сквассия, Сравнение поплавкового кода

Сравнение с плавающей точкой.

Например, если мы хотим получить допуск, который мог бы соответствовать примерно 9 арифметическим операциям, скажем sqrt(9) = 3, мы могли бы определить:

T tolerance =  3 * std::numeric_limits<T>::epsilon();

Это очень широко используется в Boost. Тестирование с помощью Boost. Тестовый макрос<BOOST_CHECK_CLOSE_FRACTION>

T expected = 1.0;
T calculated = 1.0 + std::numeric_limits<T>::epsilon();
BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance);

Используется таким образом:

BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance);

(Существует также версия, использующая допуск в процентах, а не в долях).

using boost::multiprecision::number;
using boost::multiprecision::cpp_dec_float;
using boost::multiprecision::et_off;
typedef number<cpp_dec_float<50>, et_off > cpp_dec_float_50; // 50 decimal digits.
[Note] Note

Этот буст. Тест еще не позволяет сравнивать с шаблонами экспрессии с плавающей точкой, поэтому параметр шаблона экспрессии по умолчанию был заменен<et_off>.

cpp_dec_float_50 tolerance =  3 * std::numeric_limits<cpp_dec_float_50>::epsilon();
cpp_dec_float_50 expected = boost::math::constants::two_pi<cpp_dec_float_50>();
cpp_dec_float_50 calculated = 2 * boost::math::constants::pi<cpp_dec_float_50>();
BOOST_CHECK_CLOSE_FRACTION(expected, calculated, tolerance);
Infinity - positive and negative

Только для типов с плавающей запятой, для которых<std::numeric_limits<T>::has_infinity ==true>, функция<std::numeric_limits<T>::infinity()>обеспечивает определяемое реализацией представление для ∞.

«Представление» — это особый битовый шаблон, зарезервированный для бесконечности. Для системы IEEE754 (для которой<std::numeric_limits<T>::is_iec559 ==true>)положительная и отрицательная бесконечностьназначаются битовые узоры для всех заданных типов с плавающей запятой.

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

Например, выход<1.#INF>на системах Microsoft, но<inf>на большинстве *nix платформ.

Эта реализация-определённость затрудняет использование бесконечности (и NaNs), но усиливается. Математика и рост. Многоточность работы позволяет обеспечить разумное представление длявсехтипов с плавающей запятой, а не только встроенных типов, которые с использованием подходящих граней для определения входных и выходных строк позволяют использовать эти полезные функции переносимо и включая Boost.Serialization.

Not-A-Number NaN
Quiet_NaN

Для типов с плавающей запятой, для которых<std::numeric_limits<T>::has_quiet_NaN ==true>, функция<std::numeric_limits<T>::quiet_NaN()>обеспечивает заданное реализацией представление для NaN.

NaN— значения, указывающие на то, что результат назначения или вычисления бессмыслен. Типичный пример<0/0>, но есть много других.

Для представления отсутствующих значений могут также использоваться NaN: например, они могут, по условности, игнорироваться при расчетах статистики как средства.

Многие проблемы с представлением дляNot-A-Numberзатрудняют портативное использование, подобно тем, которые имеют бесконечность.

NaN может использоваться с бинарными типами многоточности, такими как<cpp_bin_float_quad>:

using boost::multiprecision::cpp_bin_float_quad;
if (std::numeric_limits<cpp_bin_float_quad>::has_quiet_NaN == true)
{
  cpp_bin_float_quad tolerance =  3 * std::numeric_limits<cpp_bin_float_quad>::epsilon();
  cpp_bin_float_quad NaN =  std::numeric_limits<cpp_bin_float_quad>::quiet_NaN();
  std::cout << "cpp_bin_float_quad NaN is "  << NaN << std::endl; //   cpp_bin_float_quad NaN is nan
  cpp_bin_float_quad expected = NaN;
  cpp_bin_float_quad calculated = 2 * NaN;
  // Comparisons of NaN's always fail:
  bool b = expected == calculated;
  std::cout << b << std::endl;
  BOOST_CHECK_NE(expected, expected);
  BOOST_CHECK_NE(expected, calculated);
}
else
{
  std::cout << "Type " << typeid(cpp_bin_float_quad).name() << " does not have NaNs!" << std::endl;
}

Но с помощью Boost. Математика и подходящие грани могут позволить портативное использование как NaN, так и положительной и отрицательной бесконечности.

См.boost:/libs/math/example/nonfinite_facet_sstream.cpp

#include <boost/math/special_functions/nonfinite_num_facets.hpp>

Тогда мы также можем использовать многоточный тип cpp_bin_float_quad:

using boost::multiprecision::cpp_bin_float_quad;
typedef cpp_bin_float_quad T;
using boost::math::nonfinite_num_put;
using boost::math::nonfinite_num_get;
{
  std::locale old_locale;
  std::locale tmp_locale(old_locale, new nonfinite_num_put<char>);
  std::locale new_locale(tmp_locale, new nonfinite_num_get<char>);
  std::stringstream ss;
  ss.imbue(new_locale);
  T inf = std::numeric_limits<T>::infinity();
  ss << inf; // Write out.
  assert(ss.str() == "inf");
  T r;
  ss >> r; // Read back in.
  assert(inf == r); // Confirms that the floating-point values really are identical.
  std::cout << "infinity output was " << ss.str() << std::endl;
  std::cout << "infinity input was " << r << std::endl;
}
infinity output was inf
infinity input was inf

Точно так же мы можем сделать то же самое с NaN (кроме того, что мы не можем использовать<assert>).

{
  std::locale old_locale;
  std::locale tmp_locale(old_locale, new nonfinite_num_put<char>);
  std::locale new_locale(tmp_locale, new nonfinite_num_get<char>);
  std::stringstream ss;
  ss.imbue(new_locale);
  T n;
  T NaN = std::numeric_limits<T>::quiet_NaN();
  ss << NaN; // Write out.
  assert(ss.str() == "nan");
  std::cout << "NaN output was " << ss.str() << std::endl;
  ss >> n; // Read back in.
  std::cout << "NaN input was " << n << std::endl;
}

NaN вход был NaN вход был Nan

Signaling NaN

Только для типов с плавающей запятой, для которых<std::numeric_limits<T>::has_signaling_NaN ==true>, функция<std::numeric_limits<T>::signaling_NaN()>обеспечивает заданное реализацией представление для NaN, которое вызывает аппаратную ловушку. Следует отметить, однако, что по меньшей мере одна реализация этой функции вызывает аппаратную ловушку, которая вызывается просто вызовом<std::numeric_limits<T>::signaling_NaN()>, а не только использованием возвращаемого значения.


PrevUpHomeNext

Статья std::numeric_limits<> functions раздела Chapter 1. Boost.Multiprecision Numeric Limits может быть полезна для разработчиков на c++ и boost.




Материалы статей собраны из открытых источников, владелец сайта не претендует на авторство. Там где авторство установить не удалось, материал подаётся без имени автора. В случае если Вы считаете, что Ваши права нарушены, пожалуйста, свяжитесь с владельцем сайта.



:: Главная :: Numeric Limits ::


реклама


©KANSoftWare (разработка программного обеспечения, создание программ, создание интерактивных сайтов), 2007
Top.Mail.Ru

Время компиляции файла: 2024-08-30 11:47:00
2025-05-19 18:26:49/0.012866973876953/1