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

Rational Number Library

Boost , ,

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

Rational Numbers

Contents

  1. Рациональный синопсис
  2. Обоснование
  3. Предыстория
  4. Требования к целочисленным типам
  5. Интерфейс
  6. Исполнение
  7. Исключения
  8. Внутренняя репрезентация
  9. Примечания к проекту
  10. Ссылки
  11. История и признания

Class rational synopsis

#include <boost/rational.hpp>
namespace boost {
class bad_rational;
template<typename I> class rational {
    typedef implementation-defined bool_type;
public:
    typedef I int_type;
    // Constructors
    constexpr rational();          // Zero
    constexpr rational(I n);       // Equal to n/1
              rational(I n, I d);  // General case (n/d)
   template<typename J>
    constexpr explicit rational(const rational<J> &r);  // Cross-instantiation
    // Normal copy constructors and assignment operators
    // Assignment from I
    rational& operator=(I n);
    // Assign in place
    rational& assign(I n, I d);
    // Representation
    constexpr I numerator() const;
    constexpr I denominator() const;
    // In addition to the following operators, all of the "obvious" derived
    // operators are available - see operators.hpp
    // Arithmetic operators
    rational& operator+= (const rational& r);
    rational& operator-= (const rational& r);
    rational& operator*= (const rational& r);
    rational& operator/= (const rational& r);
    // Arithmetic with integers
    rational& operator+= (I i);
    rational& operator-= (I i);
    rational& operator*= (I i);
    rational& operator/= (I i);
    // Increment and decrement
    const rational& operator++();
    const rational& operator--();
    // Operator not
    constexpr bool operator!() const;
    // Boolean conversion
    constexpr operator bool_type() const;
    // Comparison operators
              bool operator< (const rational& r) const;
    constexpr bool operator== (const rational& r) const;
    // Comparison with integers
              bool operator< (I i) const;
              bool operator> (I i) const;
    constexpr bool operator== (I i) const;
};
// Unary operators
template <typename I> constexpr rational<I> operator+ (const rational<I>& r);
template <typename I>           rational<I> operator- (const rational<I>& r);
// Reversed order operators for - and / between (types convertible to) I and rational
template <typename I, typename II> inline rational<I> operator- (II i, const rational<I>& r);
template <typename I, typename II> inline rational<I> operator/ (II i, const rational<I>& r);
// Absolute value
template <typename I> rational<I> abs (const rational<I>& r);
// Input and output
template <typename I> std::istream& operator>> (std::istream& is, rational<I>& r);
template <typename I> std::ostream& operator<< (std::ostream& os, const rational<I>& r);
// Type conversion
template <typename T, typename I> constexpr T rational_cast (const rational<I>& r);

Rationale

Numbers come in many different forms. The most basic forms are natural numbers (non-negative "whole" numbers), integers and real numbers. These types are approximated by the C++ built-in types unsigned int, int, and float (and their various equivalents in different sizes).

Стандартная библиотека C++ расширяет диапазон числовых типов, предоставляя комплекс.

Эта библиотека предоставляет дополнительный численный тип,рациональныечисла.

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

Предыстория

Математическая концепция рационального числа — это то, что обычно считается дробью, то есть число, которое можно представить как отношение двух целых чисел. Это понятие отличается от понятия реального числа, которое может принимать гораздо больше значений (например, квадратный корень из 2, который не может быть представлен как дробь).

Компьютеры не могут точно представлять математические понятия — всегда есть компромиссы. Целые числа машин имеют ограниченный диапазон значений (часто 32 бита), а приближения машин к реалам ограничены по точности. Компромиссы имеют разную мотивацию — целые числа машин позволяют точный расчет, но с ограниченным диапазоном, тогда как реалы машин позволяют гораздо больший диапазон, но за счет точности.

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

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

Требования к целочисленным типам

Рациональный тип принимает один параметр типа шаблона I. Этоосновной целочисленный типдля рационального типа. Любой из встроенных целочисленных типов, предоставляемых реализацией C++, поддерживается в качестве значений для I. Могут также использоваться определяемые пользователем типы, но пользователи должны знать, что эксплуатационные характеристики рационального класса сильно зависят от эксплуатационных характеристик базового целого типа (часто сложными способами - для конкретных заметок см. разделПроизводительностьниже). Примечание: Если в будущем библиотека бустеров будет поддерживать неограниченно точный целочисленный тип, этот тип будет полностью поддерживаться как основной целочисленный тип для рационального класса.

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

  • Assignable
  • Default Constructible
  • Equality Comparable
  • LessThan Comparable

Кроме того, я должен бытьцелочисленнымтипом, то есть следующие выражения должны быть действительны для любых двух значений n и m типа I, с «ожидаемой» семантикой.

  • <n + m>
  • <n - m>
  • <n * m>
  • <n / m>(должен быть усечен; должен быть неотрицательным, еслиnиmявляются положительными)
  • <n % m>(должен быть неотрицательным, еслиnиmявляются положительными)
  • Назначение версий выше
  • <+n>,<-n>
  • <!n>(должно быть<true>iffnравно нулю)

нольиоднозначения доступны для I. Их можно было бы сгенерировать какI(0)иI(1)соответственно.Примечание:Это не означает, что я должен иметь неявное преобразование из целого числа —явныйконструктор является адекватным.

Для меня действительно быть неподписанным. В этом случае производный рациональный класс также будет неподписан. Поведение вычитания, при котором результаты в противном случае были бы отрицательными, в этом случае непредсказуемо.

  • Реализация рационального_cast(рационального) опирается на способность статического_cast от типа I до типа T и на то, что выражение x/y справедливо для любых двух значений типа T.
  • Операторы ввода и вывода полагаются на существование соответствующих операторов ввода и вывода для типа I
.

Специализация<std::numeric_limits<I>>должна существовать (и должна быть видна до<boost::rational<I>>. Значение его<is_specialized>статического элемента данных должно бытьистинным, а значение его<is_signed>статического элемента данных должно быть точным.

Интерфейс

Функции полезности

Могут быть предусмотрены два шаблона функций полезности, которые должны работать слюбым типом, который может использоватьсяс шаблоном класса<boost::rational<>>.

gcd(n, m) Самый большой общий делитель n и m
lcm(n, m) Наименее общее кратное n и m

Эти шаблоны функций теперь пересылают вызовы своим эквивалентам вBoost. Целая библиотека. Их присутствие можно контролировать во время компиляции с постоянной препроцессора<BOOST_CONTROL_RATIONAL_HAS_GCD>.

Конструкторы

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

Рационалы также могут быть построены из другого рационального. Когда источник и пункт назначения, лежащие в основе целых типов чисел, совпадают, используется автоматически определенный конструктор копий или движений. В противном случае используется шаблон конвертирующего конструктора. Конструктор выполняет инициализацию числителя и знаменателя по принципу члена. Преобразования на уровне компонентов, которые отмечены<explicit>, хороши. Когда конверсия заканчивается сохранением ценности, она уже нормализуется; но проверка на нормализацию выполняется в случае нарушения сохранения ценности.

Это означает, что следующие утверждения действительны:<

    I n, d;
    rational<I> zero;
    rational<I> r1(n);
    rational<I> r2(n, d);
    rational<J> r3(r2);  // assuming J(n) and J(d) are well-formed
>

Конструктор без аргументов, конструктор с одним аргументом и шаблон конструктора с кросс-версией помечены как<constexpr>, что делает их жизнеспособными в постоянных выражениях, когда инициализаторы (если таковые имеются) также являются постоянными выражениями (и необходимые операции из базового целого типа(ов)<constexpr>-включены).

Конструктор единого аргументанеобъявлен явным, поэтому существует неявное преобразование из базового целого типа в рациональный тип. Конструктор с двумя аргументами можно считать неявным преобразованием с однородным синтаксисом инициализации C++11, поскольку он также не объявлен явным. Шаблон конструктора кросс-версии объявлен явным, поэтому необходимо указать направление преобразования между двумя рациональными инстанциациями.

Арифметические операции

Все стандартные числовые операторы определены длярациональногокласса. К ним относятся:
<
    +    +=
    -    -=
    *    *=
    /    /=
    ++   --    (both prefix and postfix)
    ==   !=
    <    >
    <=   >=
    Unary: + - !
>

До сих пор только<operator ==>, unary<operator +>и<operator !>являются<constexpr>.

Ввод и вывод

Предоставляются операторы ввода и вывода<<и>>. Внешнее представление рационального представляет собой два целых числа, разделенных косой чертой/. На входе формат должен быть точно целым числом, за которым следует без промежуточного белого пространства слэш, а за ним (опять же без промежуточного белого пространства) второе целое число. Внешнее представление целого числа определяется неотчуждающим целым типом.

Назначение места

Для любогорациональногоr,r.assign(n, m)обеспечивает альтернативуr = рациональному(n, m);, без конструирования временного. Хотя это, вероятно, не нужно для рационалов, основанных на целочисленных типах машин, это может обеспечить экономию для рационалов, основанных, например, на неограниченных целочисленных числах.

Функция бросит, если данные компоненты не могут быть сформированы в действительное рациональное число. В противном случае он может бросать только в том случае, если может бросать назначение движения на уровне компонента (в C++11; копирование для более ранних версий C++). Сильная гарантия сохраняется, если бросок происходит в первой части, но существует риск того, что ни сильная, ни базовая гарантия не произойдет, если исключение будет брошено во время заданий компонентов.

Конверсии

Существует оператор преобразования в неопределенный булевый тип (скорее всего, указатель участника). Этот оператор преобразует рациональное в<false>, если оно представляет собой ноль, и<true>в противном случае. Это преобразование позволяет рационально использовать в качестве первого аргумента оператора<?:>; в качестве либо аргумента операторов<&&>или<||>без потери оценки короткого замыкания; в качестве условия для утверждения<do>,<if>,<while>или<for>; и в качестве условного заявления для утверждений<if>,<while>или<for>. Природа используемого типа и то, что любые имена для этой природы хранятся в тайне, должны предотвращать любое ненадлежащее небулевое использование, такое как числовые или указательные операции или как<switch>условие.

Нетдругихнеявных превращений из рационального типа. Помимо явного шаблона конструктора кросс-версии, существует явная функция преобразования типаrational_cast(r). Это можно использовать следующим образом:<

    rational<int> r(22,7);
    double nearly_pi = boost::rational_cast<double>(r);
>

Поведение функцииrational_castне определено, если числитель или знаменатель источника рационального не может быть безопасно отброшен на соответствующий тип плавающей точки, или если разделение числителя и знаменателя (в типе целевой плавающей точки) не оценивается правильно. Кроме того, поскольку эта функция имеет собственное имя, ее нельзя назвать общим кодом для торговли между двумя инстанциациями одного и того же шаблона класса, в отличие от конструктора кросс-версии.

По существу, все требуемые преобразования должны сохранять ценность, и все операции должны вести себя «разумно». Если эти ограничения не могут быть выполнены, будет более целесообразным отдельное пользовательское преобразование.

Булева конверсия ирациональное_cast<constexpr>-включено.

Записка об осуществлении:

Реализация функции рационального кастинга<

    template <typename Float, typename Int>
    Float rational_cast(const rational<Int>& src)
    {
        return static_cast<Float>(src.numerator()) / src.denominator();
    }
>Программы не должны быть написаны, чтобы зависеть от этой реализации, тем более, что эта реализация в настоящее время устарела. (Требуется смешанное разделение типовFloatиInt, в отличие отInteger Type Requirements.)

Номератор и номинатор

Наконец, доступ к внутреннему представлению рациональностей обеспечивается двумя функциями-членамичислитель()изнаменатель(). Эти функции включены<constexpr>.

Эти функции позволяют коду пользователя реализовать любую дополнительную требуемую функциональность. В частности, следует отметить, что могут быть случаи, когда вышеупомянутая операция рационального броска неуместна, особенно в тех случаях, когда рациональный тип основан на неограниченном целочисленном типе. В этом случае более подходящим будет специально написанное пользовательское преобразование в плавающую точку.

Производительность

Рациональный класс был разработан с неявным предположением, что основной целочисленный тип будет действовать «как» встроенный в целочисленные типы. Поведенческие аспекты этого предположения были явно описаны выше в разделеТребования к целому типу. Однако, помимо поведенческих предположений, существуют неявные допущения эффективности.

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

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

  • Построение рационального — это, по существу, всего две конструкции основного целого типа плюс нормализация.
  • Операции сложения и вычитания по существу так же дешевы, как сложение и вычитание по базовому целому типу.
  • (В) Сравнение неравенства по существу столь же дешево, как две операции равенства по базовому целому типу.
  • Операции ввода-вывода не дешевы, но их производительность в основном зависит от времени ввода-вывода.
  • Обычный вызов (имплицитный) GCD по существу представляет собой повторную операцию модуля. Другими важными операциями являются строительство, присвоение и сравнение с нулевым значением IntType. Эти последние операции считаются тривиальными по сравнению с операцией модуля.
  • Операция LCM по существу представляет собой GCD плюс умножение, деление и сравнение.
  • Операции сложения и вычитания являются сложными. Для них потребуется приблизительно две операции gcd, 3 деления, 3 умножения и добавление к основному целому типу.
  • Операции умножения и деления требуют двух операций gcd, двух умножений и четырех делений.
  • Операция сравнения с целым выполняет одно целое деление & модульная пара, максимум одно дополнительное целое сложение и декремент, и максимум три целых сравнения.
  • Сравнительно-рациональная операция выполняет две операции GCD двойного размера, два дополнительных дополнения и сокращения и три сравнения в худшем случае. (Операции GCD имеют двойной размер, поскольку они выполняются по частям, а промежуточные коэффициенты сохраняются и сравниваются, тогда как прямая функция GCD сохраняет и сравнивает только остальные.)
  • Последняя фундаментальная операция — нормализация рационального. Эта операция выполняется всякий раз, когда рациональное построено (и назначено на месте). Все остальные операции аккуратно поддерживают рациональность в нормализованном состоянии. Нормализация обходится в сумму, эквивалентную одному ВВП и двум подразделениям.

Обратите внимание, что подразумевается, что операции на IntType имеют «обычные» эксплуатационные характеристики — в частности, что дорогостоящие операции являются умножением, делением и модулем, при этом сложение и вычитание значительно дешевле. Предполагается, что строительство (от целых букв 0 и 1, а также копирование строительства) и присвоение относительно дешевы, хотя некоторые усилия предпринимаются для уменьшения ненужного строительства и копирования. Также предполагается, что сравнение (особенно с нулем) дешево.

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

Исключения

Рационалы никогда не могут иметь нулевой знаменатель. (Эта библиотека не поддерживает представления бесконечности или NaN). Если рациональный результат когда-либо генерирует нулевой знаменатель или иным образом терпит неудачу во время нормализации, исключениеповышает:(подклассstd::domain_error). Это должно происходить только в том случае, если пользователь пытается явно построить рациональное с нулевым знаменателем, разделить рациональное на нулевое значение или создать отрицательный знаменатель, слишком большой, чтобы его можно было нормализовать. Исключение может быть выброшено во время перекрестного инсталляционного преобразования, когда по меньшей мере один из компонентов в конечном итоге не сохраняет свою ценность и новая комбинация не считается нормализованной.

Кроме того, если операции на базовом целочисленном типе могут генерировать исключения, они будут распространяться из операций на рациональный класс. Никаких особых предположений делать не следует — можно только предположить, что любые исключения, которые могут быть брошены целым классом, могут быть брошены любой рациональной операцией. В частности, рациональный конструктор может отбрасывать исключения из базового целого типа в результате этапа нормализации. Единственным исключением из этого правила является то, что рациональный деструктор будет бросать только исключения, которые могут быть брошены деструктором основного целого типа (обычно нет).

Если оператор(ы) назначения уровня компонента может (могут) бросить, то инварианты рационального объекта могут быть нарушены, если во время назначения второго компонента происходит исключение. (Здесь также указана функция<assign>). Это нарушает как сильные, так и базовые гарантии.

Внутреннее представление

Примечание:Эта информация только для информации. Программы не должны быть написаны таким образом, чтобы полагаться на эти детали реализации.

Внутри рациональные числа хранятся как пара (числитель, знаменатель) целых чисел (тип которых указан как шаблонный параметр для рационального типа). Рационалы всегда хранятся в полностью нормализованном виде (т.е. gcd (числитель, знаменатель) = 1, а знаменатель всегда положительный).

Примечания к проекту

Минимальная реализация

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

Области, в которых это минимальное соображение было смягчено, обеспечивают операторов ввода/вывода и rational_cast. Первый, как правило, бесспорен. Тем не менее, существует ряд случаев, когда рациональное преобразование не является наилучшим способом для преобразования рационального в значение с плавающей точкой (в частности, когда задействованы определенные пользователем типы). В этих случаях может и должно быть реализовано определенное пользователем преобразование. Нет необходимости называть такую операцию рациональной_cast, и поэтому функция рациональной_castнеобеспечивает необходимую инфраструктуру для специализации/перегрузки.

Ограниченные целочисленные типы

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

К сожалению, стандарт C++ не предлагает такого класса(и в настоящее время не повышает). Поэтому вполне вероятно, что класс рациональных чисел во многих случаях будет использоваться с ограниченно точными целыми типами, такими как встроенныйintтип.

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

В качестве простой иллюстрации проблем, связанных с ограниченными целыми числами точности, рассмотрим случай, когда тип C++intпредставляет собой 32-битное подписанное представление. В этом случае наименьший возможный положительный рациональныйсоставляет1/0x7FFFFFFF. Другими словами, «гранулярность» рационального представления вокруг нуля составляет приблизительно 4,66e-10. На другом конце репрезентабельного диапазона наибольший репрезентабельный рациональныйсоставляет0x7FFFFFFF/1, а следующий нижний репрезентабельный рациональныйсоставляет0x7FFFFFFE/1. Таким образом, на этом конце репрезентируемого диапазона гранулярность ia 1. Этот тип величинозависимой гранулярности типичен для представлений с плавающей точкой. Однако при использовании рационального класса чисел он не «чувствует» себя естественным.

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

Пользователю рационального типа, основанного на целочисленном типе с ограниченной точностью, необходимо знать и кодировать в ожидании таких проблем.

Преобразование из плавающей точки

Библиотека не предлагает функцию преобразования из плавающей точки в рациональную. Был получен ряд запросов на такое преобразование, но обширные дискуссии по списку повышения пришли к выводу, что «лучшего решения» проблемы нет. Поскольку нет причин, по которым пользователь библиотеки не может написать свою собственную функцию преобразования, которая соответствует его конкретным требованиям, было принято решение не выбирать какой-либо один алгоритм в качестве «стандарта».

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

    // These two values could in practice be obtained from user input,
    // or from some form of measuring instrument.
    double x = 1.0;
    double y = 3.0;
    double z = x/y;
    rational<I> r = rational_from_double(z);
>

Фундаментальный вопрос заключается в том, что именно должно быть рациональным? Наивный ответ заключается в том, что r должно быть равно 1/3. Однако это игнорирует множество вопросов.

В первом случае z не является точно 1/3. Из-за ограничений представления с плавающей точкой 1/3 не может быть точно представлено ни в одном из общих представлений для двойного типа. Следовательно, не должен ли r содержать (точное) представление фактической величины, представленной z? Но будет ли пользователь доволен значением 333333333333331/100000000000000000000 для r?

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

Все это означает, что мы должны искать какую-то форму «ближайшей простой фракции». Алгоритмы для определения такого рода значений существуют. Однако не все приложения хотят работать так. В других случаях весь смысл преобразования в рациональное состоит в том, чтобы получить точное представление, чтобы предотвратить потерю точности во время ряда вычислений. При этом требуется совершенно точное представление, независимо от того, как выглядят «неестественные» фракции.

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

Абсолютное значение

В первом случае представляется логичным реализовать abs(rational) в терминах abs(IntType). Однако есть ряд вопросов, которые возникают при этом.

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

Вторая и потенциально более серьезная проблема заключается в том, что для нестандартных встроенных целых типов (например, 64-битных целых типов, таких какдлинноеили__int64) нет никакой гарантии, что поставщик поставил встроенную функцию abs(), работающую на таких типах. Это проблема качества реализации, но с практической точки зрения поддержка поставщиков для таких типов, каки, по-прежнему очень неоднородна.

Вследствие этих проблем представляется нецелесообразным применять abs(rational) в терминах abs(IntType). Вместо этого используется простая реализация с встроенной реализацией abs():<

    template <typename IntType>
    inline rational<IntType> abs(const rational<IntType>& r)
    {
        if (r.numerator() >= IntType(0))
            return r;
            return rational<IntType>(-r.numerator(), r.denominator());
    }
>

Те же самые аргументы подразумевают, что там, где в другом месте требуется абсолютное значение IntType, вычисление выполняется inline.

Ссылки

История и признания

В декабре 1999 года я внедрил начальную версию класса рациональных чисел и представил ее в список рассылкиboost.org. Некоторое обсуждение вопроса об осуществлении состоялось в перечне рассылки. В частности, Эндрю Д. Джуэлл указал на важность обеспечения минимизации риска перелива и обеспечения беспереливных реализаций большинства основных операций. Название rational_cast предложил Кевлин Хенни. Эдди Брей предоставил неоценимые комментарии — не в последнюю очередь указав на некоторые довольно глупые ошибки при наборе текста в исходном коде!

Дэвид Абрахамс дал полезные отзывы о документации.

Долгое обсуждение достоинств обеспечения перехода от плавающей точки к рациональной состоялось в ноябре 2000 года. Ключевые участники включали Реджи Сигрейвса, Лутца Кеттнера и Дэниела Фрая (хотя большая часть списка, казалось, была вовлечена в тот или иной момент!). Несмотря на то, что конечным результатом было решениененичего реализовать, обсуждение было очень ценным для понимания вопросов.

Стивен Сильвер внес полезный вклад в использование рационального класса с определяемым пользователем целым типом.

Николай Младенов обеспечил текущую реализацию оператора+= и оператор-=.

Обсуждение вопросов, связанных с Koenig lookup и std::swap, состоялось в январе 2001 года.

Дэрил Уокер (Daryle Walker) в декабре 2005 года предоставил булеву конверсионную систему, позволяющую рационально использовать ее в том же булевом контексте, что и встроенные цифровые типы. Он добавил шаблон перекрестного обоснования в августе 2013 года.

Пересмотрено 30 августа 2013

© Copyright Paul Moore 1999-2001; © Daryle Walker 2005, 2013. Разрешение на копирование, использование, изменение, продажу и распространение этого документа предоставляется при условии, что это уведомление об авторских правах появляется во всех копиях. Этот документ предоставляется "как есть" без явной или подразумеваемой гарантии и без претензий относительно его пригодности для любых целей.

Статья Rational Number Library раздела может быть полезна для разработчиков на c++ и boost.




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



:: Главная :: ::


реклама


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

Время компиляции файла: 2024-08-30 11:47:00
2025-05-20 09:50:33/0.016913890838623/0