rational.html 36 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768
  1. <!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
  2. <html>
  3. <head>
  4. <meta http-equiv="Content-Type" content="text/html; charset=iso-8859-1">
  5. <title>Rational Number Library</title>
  6. </head>
  7. <body>
  8. <h1><img src="../../boost.png" alt="boost.png (6897 bytes)"
  9. align="middle" width="277" height="86">
  10. Rational Numbers</h1>
  11. <h2><a name="Contents">Contents</a></h2>
  12. <ol>
  13. <li><a href="#Class%20rational%20synopsis">Class rational synopsis</a></li>
  14. <li><a href="#Rationale">Rationale</a></li>
  15. <li><a href="#Background">Background</a></li>
  16. <li><a href="#Integer%20Type%20Requirements">Integer Type Requirements</a></li>
  17. <li><a href="#Interface">Interface</a>
  18. <ul>
  19. <li><a href="#Utility%20functions">Utility functions</a></li>
  20. <li><a href="#Constructors">Constructors</a></li>
  21. <li><a href="#Arithmetic%20operations">Arithmetic operations</a></li>
  22. <li><a href="#Input%20and%20Output">Input and Output</a></li>
  23. <li><a href="#In-place%20assignment">In-place assignment</a></li>
  24. <li><a href="#Conversions">Conversions</a></li>
  25. <li><a href="#Numerator%20and%20Denominator">Numerator and Denominator</a></li>
  26. </ul></li>
  27. <li><a href="#Performance">Performance</a></li>
  28. <li><a href="#Exceptions">Exceptions</a></li>
  29. <li><a href="#Internal%20representation">Internal representation</a></li>
  30. <li><a href="#Design%20notes">Design notes</a>
  31. <ul>
  32. <li><a href="#Minimal%20Implementation">Minimal Implementation</a></li>
  33. <li><a href="#Limited-range%20integer%20types">Limited-range integer types</a></li>
  34. <li><a href="#Conversion%20from%20floating%20point">Conversion from floating point</a></li>
  35. <li><a href="#Absolute%20Value">Absolute Value</a></li>
  36. </ul></li>
  37. <li><a href="#References">References</a></li>
  38. <li><a href="#History%20and%20Acknowledgements">History and Acknowledgements</a></li>
  39. </ol>
  40. <h2><a name="Class rational synopsis">Class rational synopsis</a></h2>
  41. <pre>
  42. #include &lt;boost/rational.hpp&gt;
  43. namespace boost {
  44. class bad_rational;
  45. template&lt;typename I&gt; class rational {
  46. typedef <em>implementation-defined</em> bool_type;
  47. public:
  48. typedef I int_type;
  49. // Constructors
  50. rational(); // Zero; constexpr since C++11
  51. rational(I n); // Equal to n/1; constexpr since C++11
  52. rational(I n, I d); // General case (n/d); constexpr since C++14
  53. template&lt;typename J&gt;
  54. explicit rational(const rational&lt;J&gt; &amp;r); // Cross-instantiation; constexpr since C++11
  55. // Normal copy constructors and assignment operators
  56. // Assignment from I
  57. rational&amp; operator=(I n); // constexpr since C++14
  58. // Assign in place
  59. rational&amp; assign(I n, I d); // constexpr since C++14
  60. // Representation
  61. I numerator() const; // constexpr since C++11
  62. I denominator() const; // constexpr since C++11
  63. // In addition to the following operators, all of the "obvious" derived
  64. // operators are available - see <a href="../utility/operators.htm">operators.hpp</a>
  65. // Arithmetic operators
  66. rational&amp; operator+= (const rational&amp; r); // constexpr since C++14
  67. rational&amp; operator-= (const rational&amp; r); // constexpr since C++14
  68. rational&amp; operator*= (const rational&amp; r); // constexpr since C++14
  69. rational&amp; operator/= (const rational&amp; r); // constexpr since C++14
  70. // Arithmetic with integers
  71. rational&amp; operator+= (I i); // constexpr since C++14
  72. rational&amp; operator-= (I i); // constexpr since C++14
  73. rational&amp; operator*= (I i); // constexpr since C++14
  74. rational&amp; operator/= (I i); // constexpr since C++14
  75. // Increment and decrement
  76. const rational&amp; operator++(); // constexpr since C++14
  77. const rational&amp; operator--(); // constexpr since C++14
  78. // Operator not
  79. bool operator!() const; // constexpr since C++11
  80. // Boolean conversion
  81. operator bool_type() const; // constexpr since C++11
  82. // Comparison operators
  83. bool operator&lt; (const rational&amp; r) const; // constexpr since C++14
  84. bool operator== (const rational&amp; r) const; // constexpr since C++11
  85. // Comparison with integers
  86. bool operator&lt; (I i) const; // constexpr since C++14
  87. bool operator&gt; (I i) const; // constexpr since C++14
  88. bool operator== (I i) const; // constexpr since C++11
  89. };
  90. // Unary operators
  91. template &lt;typename I&gt; rational&lt;I&gt; operator+ (const rational&lt;I&gt;&amp; r); // constexpr since C++11
  92. template &lt;typename I&gt; rational&lt;I&gt; operator- (const rational&lt;I&gt;&amp; r); // constexpr since C++14
  93. // Reversed order operators for - and / between (types convertible to) I and rational
  94. template &lt;typename I, typename II&gt; inline rational&lt;I&gt; operator- (II i, const rational&lt;I&gt;&amp; r); // constexpr since C++14
  95. template &lt;typename I, typename II&gt; inline rational&lt;I&gt; operator/ (II i, const rational&lt;I&gt;&amp; r); // constexpr since C++14
  96. // Absolute value
  97. template &lt;typename I&gt; rational&lt;I&gt; abs (const rational&lt;I&gt;&amp; r); // constexpr since C++14
  98. // Input and output
  99. template &lt;typename I&gt; std::istream&amp; operator&gt;&gt; (std::istream&amp; is, rational&lt;I&gt;&amp; r);
  100. template &lt;typename I&gt; std::ostream&amp; operator&lt;&lt; (std::ostream&amp; os, const rational&lt;I&gt;&amp; r);
  101. // Type conversion
  102. template &lt;typename T, typename I&gt; T rational_cast (const rational&lt;I&gt;&amp; r); // constexpr since C++11
  103. </pre>
  104. <h2><a name="Rationale">Rationale</a></h2>
  105. Numbers come in many different forms. The most basic forms are natural numbers
  106. (non-negative "whole" numbers), integers and real numbers. These types are
  107. approximated by the C++ built-in types <b>unsigned int</b>, <b>int</b>, and
  108. <b>float</b> (and their various equivalents in different sizes).
  109. <p>The C++ Standard Library extends the range of numeric types available by
  110. providing the <b>complex</b> type.
  111. <p>This library provides a further numeric type, the <b>rational</b> numbers.
  112. <p>The <b>rational</b> class is actually a implemented as a template, in a
  113. similar manner to the standard <b>complex</b> class.
  114. <h2><a name="Background">Background</a></h2>
  115. The mathematical concept of a rational number is what is commonly thought of
  116. as a fraction - that is, a number which can be represented as the ratio of two
  117. integers. This concept is distinct from that of a real number, which can take
  118. on many more values (for example, the square root of 2, which cannot be
  119. represented as a fraction).
  120. <p>
  121. Computers cannot represent mathematical concepts exactly - there are always
  122. compromises to be made. Machine integers have a limited range of values (often
  123. 32 bits), and machine approximations to reals are limited in precision. The
  124. compromises have differing motivations - machine integers allow exact
  125. calculation, but with a limited range, whereas machine reals allow a much
  126. greater range, but at the expense of exactness.
  127. <p>
  128. The rational number class provides an alternative compromise. Calculations
  129. with rationals are exact, but there are limitations on the available range. To
  130. be precise, rational numbers are exact as long as the numerator and
  131. denominator (which are always held in normalized form, with no common factors)
  132. are within the range of the underlying integer type. When values go outside
  133. these bounds, overflow occurs and the results are undefined.
  134. <p>
  135. The rational number class is a template to allow the programmer to control the
  136. overflow behaviour somewhat. If an unlimited precision integer type is
  137. available, rational numbers based on it will never overflow (modulo resource
  138. limits) and will provide exact calculations in all circumstances.
  139. <h2><a name="Integer Type Requirements">Integer Type Requirements</a></h2>
  140. <p> The rational type takes a single template type parameter I. This is the
  141. <em>underlying integer type</em> for the rational type. Any of the built-in
  142. integer types provided by the C++ implementation are supported as values for
  143. I. User-defined types may also be used, but users should be aware that the
  144. performance characteristics of the rational class are highly dependent upon
  145. the performance characteristics of the underlying integer type (often in
  146. complex ways - for specific notes, see the <a href="#Performance">Performance</a>
  147. section below). Note: Should the boost library support an unlimited-precision
  148. integer type in the future, this type will be fully supported as the underlying
  149. integer type for the rational class.
  150. </p>
  151. <p>
  152. A user-defined integer type which is to be used as the underlying integer type
  153. for the rational type must be a model of the following concepts.
  154. </p>
  155. <ul>
  156. <li>Assignable
  157. <li>Default Constructible
  158. <li>Equality Comparable
  159. <li>LessThan Comparable
  160. </ul>
  161. <p>
  162. Furthermore, I must be an <em>integer-like</em> type, that is the following
  163. expressions must be valid for any two values n and m of type I, with the
  164. "expected" semantics.
  165. <ul>
  166. <li><code>n + m</code>
  167. <li><code>n - m</code>
  168. <li><code>n * m</code>
  169. <li><code>n / m</code> (must truncate; must be nonnegative if <var>n</var> and
  170. <var>m</var> are positive)
  171. <li><code>n % m</code> (must be nonnegative if <var>n</var> and <var>m</var>
  172. are positive)
  173. <li>Assignment versions of the above
  174. <li><code>+n</code>, <code>-n</code>
  175. <li><code>!n</code> (must be <code>true</code> iff <var>n</var> is zero)
  176. </ul>
  177. <p>
  178. There must be <em>zero</em> and <em>one</em> values available for I. It should
  179. be possible to generate these as <tt>I(0)</tt> and <tt>I(1)</tt>,
  180. respectively. <em>Note:</em> This does not imply that I needs to have an
  181. implicit conversion from integer - an <tt>explicit</tt> constructor is
  182. adequate.
  183. <p>
  184. It is valid for I to be an unsigned type. In that case, the derived rational
  185. class will also be unsigned. Underflow behaviour of subtraction, where results
  186. would otherwise be negative, is unpredictable in this case.
  187. <ul>
  188. <li>
  189. The implementation of rational_cast&lt;T&gt;(rational&lt;I&gt;) relies on the
  190. ability to static_cast from type I to type T, and on the expression x/y being
  191. valid for any two values of type T.
  192. <li>
  193. The input and output operators rely on the existence of corresponding input
  194. and output operators for type I.
  195. </ul>
  196. <p>
  197. The <code>std::numeric_limits&lt;I&gt;</code> specialization must exist (and be
  198. visible before <code>boost::rational&lt;I&gt;</code> needs to be specified).
  199. The value of its <code>is_specialized</code> static data member must be
  200. <var>true</var> and the value of its <code>is_signed</code> static data member
  201. must be accurate.
  202. <h2><a name="Interface">Interface</a></h2>
  203. <h3><a name="Utility functions">Utility functions</a></h3>
  204. <p>Two utility function templates may be provided, that should work with <a
  205. href="#Integer%20Type%20Requirements">any type that can be used</a> with the
  206. <code>boost::rational&lt;&gt;</code> class template.</p>
  207. <table summary="Common-factor utility functions">
  208. <tr>
  209. <td width=5%></td>
  210. <td><tt>gcd(n, m)</tt></td>
  211. <td width=5%></td>
  212. <td>The greatest common divisor of n and m</td>
  213. </tr>
  214. <tr>
  215. <td width=5%></td>
  216. <td><tt>lcm(n, m)</tt></td>
  217. <td width=5%></td>
  218. <td>The least common multiple of n and m</td>
  219. </tr>
  220. </table>
  221. <p>These function templates now forward calls to their equivalents in the <a
  222. href="../integer/">Boost.Integer library</a>. Their presence can be controlled at
  223. compile time with the <code>BOOST_CONTROL_RATIONAL_HAS_GCD</code> preprocessor
  224. constant.
  225. <h3><a name="Constructors">Constructors</a></h3>
  226. <p>Rationals can be constructed from zero, one, or two integer arguments;
  227. representing default construction as zero, conversion from an integer posing as
  228. the numerator with an implicit denominator of one, or a numerator and
  229. denominator pair in that order, respectively. An integer argument should be of
  230. the rational's integer type, or implicitly convertible to that type. (For the
  231. two-argument constructor, any needed conversions are evaluated independently,
  232. of course.) The components are stored in normalized form.
  233. <p>Rationals can also be constructed from another rational. When the source and
  234. destination underlying integer types match, the automatically-defined copy- or
  235. move-constructor is used. Otherwise, a converting constructor template is used.
  236. The constructor does member-wise initialization of the numerator and denominator.
  237. Component-level conversions that are marked <code>explicit</code> are fine. When
  238. the conversion ends up value-preserving, it is already normalized; but a check
  239. for normalization is performed in case value-preservation is violated.
  240. <p>These imply that the following statements are valid:
  241. <pre>
  242. I n, d;
  243. rational&lt;I&gt; zero;
  244. rational&lt;I&gt; r1(n);
  245. rational&lt;I&gt; r2(n, d);
  246. rational&lt;J&gt; r3(r2); // assuming J(n) and J(d) are well-formed
  247. </pre>
  248. <p>In C++11, the no-argument constructor, single-argument constructor, and
  249. cross-version constructor template are marked as <code>constexpr</code>, making
  250. them viable in constant-expressions when the initializers (if any) are also constant
  251. expressions (and the necessary operations from the underlying integer type(s)
  252. are <code>constexpr</code>-enabled). Since C++14, all constructors are
  253. <code>constexpr</code>-enabled.
  254. <p>The single-argument constructor is <em>not</em> declared as explicit, so
  255. there is an implicit conversion from the underlying integer type to the
  256. rational type. The two-argument constructor can be considered an implicit
  257. conversion with C++11's uniform initialization syntax, since it is also not
  258. declared explicit. The cross-version constructor template is declared explicit,
  259. so the direction of conversion between two rational instantiations must be
  260. specified.
  261. <h3><a name="Arithmetic operations">Arithmetic operations</a></h3>
  262. All of the standard numeric operators are defined for the <b>rational</b>
  263. class. These include:
  264. <br>
  265. <pre>
  266. + +=
  267. - -=
  268. * *=
  269. / /=
  270. ++ -- (both prefix and postfix)
  271. == !=
  272. &lt; &gt;
  273. &lt;= &gt;=
  274. Unary: + - !
  275. </pre>
  276. <p>Since C++14, all of these operations are <code>constexpr</code>-enabled.
  277. In C++11, only <code>operator==</code>, <code>operator!=</code>,
  278. unary <code>operator+</code>, and <code>operator!</code> are.
  279. <h3><a name="Input and Output">Input and Output</a></h3>
  280. Input and output operators <tt>&lt;&lt;</tt> and <tt>&gt;&gt;</tt>
  281. are provided. The external representation of a rational is
  282. two integers, separated by a slash (<tt>/</tt>). On input, the format must be
  283. exactly an integer, followed with no intervening whitespace by a slash,
  284. followed (again with no intervening whitespace) by a second integer. The
  285. external representation of an integer is defined by the underlying integer
  286. type.
  287. <h3><a name="In-place assignment">In-place assignment</a></h3>
  288. For any <tt>rational&lt;I&gt; r</tt>, <tt>r.assign(n, m)</tt> provides an
  289. alternate to <tt>r = rational&lt;I&gt;(n, m);</tt>, without a user-specified
  290. construction of a temporary. While this is probably unnecessary for rationals
  291. based on machine integer types, it could offer a saving for rationals based on
  292. unlimited-precision integers, for example.
  293. <p>The function will throw if the given components cannot be formed into a valid
  294. rational number. Otherwise, it could throw only if the component-level move
  295. assignment (in C++11; copy-assignment for earlier C++ versions) can throw. The
  296. strong guarantee is kept if throwing happens in the first part, but there is a
  297. risk of neither the strong nor basic guarantees happening if an exception is
  298. thrown during the component assignments.
  299. <h3><a name="Conversions">Conversions</a></h3>
  300. <p>There is a conversion operator to an unspecified Boolean type (most likely a
  301. member pointer). This operator converts a rational to <code>false</code> if it
  302. represents zero, and <code>true</code> otherwise. This conversion allows a
  303. rational for use as the first argument of operator <code>?:</code>; as either
  304. argument of operators <code>&amp;&amp;</code> or <code>||</code> without
  305. forfeiting short-circuit evaluation; as a condition for a <code>do</code>,
  306. <code>if</code>, <code>while</code>, or <code>for</code> statement; and as a
  307. conditional declaration for <code>if</code>, <code>while</code>, or
  308. <code>for</code> statements. The nature of the type used, and that any names
  309. for that nature are kept private, should prevent any inappropriate non-Boolean
  310. use like numeric or pointer operations or as a <code>switch</code> condition.
  311. <p>There are <em>no other</em> implicit conversions from a rational
  312. type. Besides the explicit cross-version constructor template, there is an
  313. explicit type-conversion function, <tt>rational_cast&lt;T&gt;(r)</tt>. This can
  314. be used as follows:
  315. <pre>
  316. rational&lt;int&gt; r(22,7);
  317. double nearly_pi = boost::rational_cast&lt;double&gt;(r);
  318. </pre>
  319. <p>The <tt>rational_cast&lt;T&gt;</tt> function's behaviour is undefined if the
  320. source rational's numerator or denominator cannot be safely cast to the
  321. appropriate floating point type, or if the division of the numerator and
  322. denominator (in the target floating point type) does not evaluate correctly.
  323. Also, since this function has a custom name, it cannot be called in generic code
  324. for trading between two instantiations of the same class template, unlike the
  325. cross-version constructor.
  326. <p>In essence, all required conversions should be value-preserving, and all
  327. operations should behave "sensibly". If these constraints cannot be met, a
  328. separate user-defined conversion will be more appropriate.
  329. <p>Boolean conversion and <tt>rational_cast</tt> are <code>constexpr</code>-enabled.
  330. <p><em>Implementation note:</em>
  331. <p>The implementation of the rational_cast function was
  332. <pre>
  333. template &lt;typename Float, typename Int&gt;
  334. Float rational_cast(const rational&lt;Int&gt;&amp; src)
  335. {
  336. return static_cast&lt;Float&gt;(src.numerator()) / src.denominator();
  337. }
  338. </pre>
  339. Programs should not be written to depend upon this implementation, however,
  340. especially since this implementation is now obsolete. (It required a mixed-mode
  341. division between types <var>Float</var> and <var>Int</var>, contrary to the <a
  342. href="#Integer%20Type%20Requirements">Integer Type Requirements</a>.)
  343. <h3><a name="Numerator and Denominator">Numerator and Denominator</a></h3>
  344. Finally, access to the internal representation of rationals is provided by
  345. the two member functions <tt>numerator()</tt> and <tt>denominator()</tt>.
  346. These functions are <code>constexpr</code>-enabled.
  347. <p>These functions allow user code to implement any additional required
  348. functionality. In particular, it should be noted that there may be cases where
  349. the above rational_cast operation is inappropriate - particularly in cases
  350. where the rational type is based on an unlimited-precision integer type. In
  351. this case, a specially-written user-defined conversion to floating point will
  352. be more appropriate.
  353. <h2><a name="Performance">Performance</a></h2>
  354. The rational class has been designed with the implicit assumption that the
  355. underlying integer type will act "like" the built in integer types. The
  356. behavioural aspects of this assumption have been explicitly described above,
  357. in the <a href="#Integer%20Type%20Requirements">Integer Type Requirements</a>
  358. section. However, in addition to behavioural assumptions, there are implicit
  359. performance assumptions.
  360. <p> No attempt will be made to provide detailed performance guarantees for the
  361. operations available on the rational class. While it is possible for such
  362. guarantees to be provided (in a similar manner to the performance
  363. specifications of many of the standard library classes) it is by no means
  364. clear that such guarantees will be of significant value to users of the
  365. rational class. Instead, this section will provide a general discussion of the
  366. performance characteristics of the rational class.
  367. <p>There now follows a list of the fundamental operations defined in the
  368. <a href="../../boost/rational.hpp"> &lt;boost/rational.hpp&gt;</a> header
  369. and an informal description of their performance characteristics. Note that
  370. these descriptions are based on the current implementation, and as such should
  371. be considered subject to change.
  372. <ul>
  373. <li>Construction of a rational is essentially just two constructions of the
  374. underlying integer type, plus a normalization.
  375. <li>Increment and decrement operations are essentially as cheap as addition and
  376. subtraction on the underlying integer type.
  377. <li>(In)equality comparison is essentially as cheap as two equality operations
  378. on the underlying integer type.
  379. <li>I/O operations are not cheap, but their performance is essentially
  380. dominated by the I/O time itself.
  381. <li>An (implicit) GCD routine call is essentially a repeated modulus operation.
  382. Its other significant operations are construction, assignment, and comparison
  383. against zero of IntType values. These latter operations are assumed to be
  384. trivial in comparison with the modulus operation.
  385. <li>The (implicit) LCM operation is essentially a GCD plus a multiplication,
  386. division, and comparison.
  387. <li>The addition and subtraction operations are complex. They will require
  388. approximately two gcd operations, 3 divisions, 3 multiplications and an
  389. addition on the underlying integer type.
  390. <li>The multiplication and division operations require two gcd operations, two
  391. multiplications, and four divisions.
  392. <li>The compare-with-integer operation does a single integer division &amp;
  393. modulus pair, at most one extra integer addition and decrement, and at most
  394. three integer comparisons.
  395. <li>The compare-with-rational operation does two double-sized GCD operations,
  396. two extra additions and decrements, and three comparisons in the worst case.
  397. (The GCD operations are double-sized because they are done in piecemeal and the
  398. interim quotients are retained and compared, whereas a direct GCD function only
  399. retains and compares the remainders.)
  400. <li>The final fundamental operation is normalizing a rational. This operation
  401. is performed whenever a rational is constructed (and assigned in place). All
  402. other operations are careful to maintain rationals in a normalized state.
  403. Normalization costs the equivalent of one gcd and two divisions.
  404. </ul>
  405. <p>Note that it is implicitly assumed that operations on IntType have the
  406. "usual" performance characteristics - specifically, that the expensive
  407. operations are multiplication, division, and modulo, with addition and
  408. subtraction being significantly cheaper. It is assumed that construction (from
  409. integer literals 0 and 1, and copy construction) and assignment are relatively
  410. cheap, although some effort is taken to reduce unnecessary construction and
  411. copying. It is also assumed that comparison (particularly against zero) is
  412. cheap.
  413. <p>Integer types which do not conform to these assumptions will not be
  414. particularly effective as the underlying integer type for the rational class.
  415. Specifically, it is likely that performance will be severely sub-optimal.
  416. <h2><a name="Exceptions">Exceptions</a></h2>
  417. Rationals can never have a denominator of zero. (This library does not support
  418. representations for infinity or NaN). Should a rational result ever generate a
  419. denominator of zero, or otherwise fail during normalization, the exception
  420. <tt>boost::bad_rational</tt> (a subclass of <tt>std::domain_error</tt>) is
  421. thrown. This should only occur if the user attempts to explicitly construct a
  422. rational with a denominator of zero, to divide a rational by a zero value, or
  423. generate a negative denominator too large to be normalized. The exception can
  424. be thrown during a cross-instantiation conversion, when at least one of the
  425. components ends up not being value-preserved and the new combination is not
  426. considered normalized.
  427. <p>In addition, if operations on the underlying integer type can generate
  428. exceptions, these will be propagated out of the operations on the rational
  429. class. No particular assumptions should be made - it is only safe to assume
  430. that any exceptions which can be thrown by the integer class could be thrown
  431. by any rational operation. In particular, the rational constructor may throw
  432. exceptions from the underlying integer type as a result of the normalization
  433. step. The only exception to this rule is that the rational destructor will
  434. only throw exceptions which can be thrown by the destructor of the underlying
  435. integer type (usually none).
  436. <p>If the component-level assignment operator(s) can throw, then a rational
  437. object's invariants may be violated if an exception happens during the second
  438. component's assignment. (The <code>assign</code> member function counts here
  439. too.) This violates both the strong and basic guarantees.
  440. <h2><a name="Internal representation">Internal representation</a></h2>
  441. <em>Note:</em> This information is for information only. Programs should not
  442. be written in such a way as to rely on these implementation details.
  443. <p>Internally, rational numbers are stored as a pair (numerator, denominator)
  444. of integers (whose type is specified as the template parameter for the
  445. rational type). Rationals are always stored in fully normalized form (ie,
  446. gcd(numerator,denominator) = 1, and the denominator is always positive).
  447. <h2><a name="Design notes">Design notes</a></h2>
  448. <h3><a name="Minimal Implementation">Minimal Implementation</a></h3>
  449. The rational number class is designed to keep to the basics. The minimal
  450. operations required of a numeric class are provided, along with access to the
  451. underlying representation in the form of the numerator() and denominator()
  452. member functions. With these building-blocks, it is possible to implement any
  453. additional functionality required.
  454. <p>Areas where this minimality consideration has been relaxed are in providing
  455. input/output operators, and rational_cast. The former is generally
  456. uncontroversial. However, there are a number of cases where rational_cast is
  457. not the best possible method for converting a rational to a floating point
  458. value (notably where user-defined types are involved). In those cases, a
  459. user-defined conversion can and should be implemented. There is no need
  460. for such an operation to be named rational_cast, and so the rational_cast
  461. function does <em>not</em> provide the necessary infrastructure to allow for
  462. specialisation/overloading.
  463. <h3><a name="Limited-range integer types">Limited-range integer types</a></h3>
  464. The rational number class is designed for use in conjunction with an
  465. unlimited precision integer class. With such a class, rationals are always
  466. exact, and no problems arise with precision loss, overflow or underflow.
  467. <p>Unfortunately, the C++ standard does not offer such a class <s>(and neither
  468. does boost, at the present time)</s>. It is therefore likely that the rational
  469. number class will in many cases be used with limited-precision integer types,
  470. such as the built-in <tt>int</tt> type.
  471. <p>When used with a limited precision integer type, the rational class suffers
  472. from many of the precision issues which cause difficulty with floating point
  473. types. While it is likely that precision issues will not affect simple uses of
  474. the rational class, users should be aware that such issues exist.
  475. <p>As a simple illustration of the issues associated with limited precision
  476. integers, consider a case where the C++ <tt>int</tt> type is a 32-bit signed
  477. representation. In this case, the smallest possible positive
  478. rational&lt;int&gt; is <tt>1/0x7FFFFFFF</tt>. In other words, the
  479. "granularity" of the rational&lt;int&gt; representation around zero is
  480. approximately 4.66e-10. At the other end of the representable range, the
  481. largest representable rational&lt;int&gt; is <tt>0x7FFFFFFF/1</tt>, and the
  482. next lower representable rational&lt;int&gt; is <tt>0x7FFFFFFE/1</tt>. Thus,
  483. at this end of the representable range, the granularity ia 1. This type of
  484. magnitude-dependent granularity is typical of floating point representations.
  485. However, it does not "feel" natural when using a rational number class.
  486. <p>Limited-precision integer types may raise issues with the range sizes of
  487. their allowable negative values and positive values. If the negative range is
  488. larger, then the extremely-negative numbers will not have an additive inverse in
  489. the positive range, making them unusable as denominator values since they cannot
  490. be normalized to positive values (unless the user is lucky enough that the input
  491. components are not relatively prime pre-normalization).
  492. <p>It is up to the user of a rational type based on a limited-precision integer
  493. type to be aware of, and code in anticipation of, such issues.
  494. <h3><a name="Conversion from floating point">Conversion from floating point</a></h3>
  495. The library does not offer a conversion function from floating point to
  496. rational. A number of requests were received for such a conversion, but
  497. extensive discussions on the boost list reached the conclusion that there was
  498. no "best solution" to the problem. As there is no reason why a user of the
  499. library cannot write their own conversion function which suits their
  500. particular requirements, the decision was taken not to pick any one algorithm
  501. as "standard".
  502. <p>The key issue with any conversion function from a floating point value is
  503. how to handle the loss of precision which is involved in floating point
  504. operations. To provide a concrete example, consider the following code:
  505. <pre>
  506. // These two values could in practice be obtained from user input,
  507. // or from some form of measuring instrument.
  508. double x = 1.0;
  509. double y = 3.0;
  510. double z = x/y;
  511. rational&lt;I&gt; r = rational_from_double(z);
  512. </pre>
  513. <p>The fundamental question is, precisely what rational should r be? A naive
  514. answer is that r should be equal to 1/3. However, this ignores a multitude of
  515. issues.
  516. <p>In the first instance, z is not exactly 1/3. Because of the limitations of
  517. floating point representation, 1/3 is not exactly representable in any of the
  518. common representations for the double type. Should r therefore not contain an
  519. (exact) representation of the actual value represented by z? But will the user
  520. be happy with a value of 33333333333333331/100000000000000000 for r?
  521. <p>Before even considering the above issue, we have to consider the accuracy
  522. of the original values, x and y. If they came from an analog measuring
  523. instrument, for example, they are not infinitely accurate in any case. In such
  524. a case, a rational representation like the above promises far more accuracy
  525. than there is any justification for.
  526. <p>All of this implies that we should be looking for some form of "nearest
  527. simple fraction". Algorithms to determine this sort of value do exist.
  528. However, not all applications want to work like this. In other cases, the
  529. whole point of converting to rational is to obtain an exact representation, in
  530. order to prevent accuracy loss during a series of calculations. In this case,
  531. a completely precise representation is required, regardless of how "unnatural"
  532. the fractions look.
  533. <p>With these conflicting requirements, there is clearly no single solution
  534. which will satisfy all users. Furthermore, the algorithms involved are
  535. relatively complex and specialised, and are best implemented with a good
  536. understanding of the application requirements. All of these factors make such
  537. a function unsuitable for a general-purpose library such as this.
  538. <h3><a name="Absolute Value">Absolute Value</a></h3>
  539. In the first instance, it seems logical to implement
  540. abs(rational&lt;IntType&gt;) in terms of abs(IntType).
  541. However, there are a number of issues which arise with doing so.
  542. <p>The first issue is that, in order to locate the appropriate implementation
  543. of abs(IntType) in the case where IntType is a user-defined type in a user
  544. namespace, Koenig lookup is required. Not all compilers support Koenig lookup
  545. for functions at the current time. For such compilers, clumsy workarounds,
  546. which require cooperation from the user of the rational class, are required to
  547. make things work.
  548. <p>The second, and potentially more serious, issue is that for non-standard
  549. built-in integer types (for example, 64-bit integer types such as
  550. <em>long long</em> or <em>__int64</em>), there is no guarantee that the vendor
  551. has supplied a built in abs() function operating on such types. This is a
  552. quality-of-implementation issue, but in practical terms, vendor support for
  553. types such as <em>long long</em> is still very patchy.
  554. <p>As a consequence of these issues, it does not seem worth implementing
  555. abs(rational&lt;IntType&gt;) in terms of abs(IntType). Instead, a simple
  556. implementation with an inline implementation of abs() is used:
  557. <pre>
  558. template &lt;typename IntType&gt;
  559. inline rational&lt;IntType&gt; abs(const rational&lt;IntType&gt;&amp; r)
  560. {
  561. if (r.numerator() &gt;= IntType(0))
  562. return r;
  563. return rational&lt;IntType&gt;(-r.numerator(), r.denominator());
  564. }
  565. </pre>
  566. <p>The same arguments imply that where the absolute value of an IntType is
  567. required elsewhere, the calculation is performed inline.
  568. <h2><a name="References">References</a></h2>
  569. <ul>
  570. <li>The rational number header itself: <a href="../../boost/rational.hpp">rational.hpp</a>
  571. <li>Some example code: <a href="test/rational_example.cpp">rational_example.cpp</a>
  572. <li>The regression test: <a href="test/rational_test.cpp">rational_test.cpp</a>
  573. </ul>
  574. <h2><a name="History and Acknowledgements">History and Acknowledgements</a></h2>
  575. <p>
  576. In December, 1999, I implemented the initial version of the rational number
  577. class, and submitted it to the <A HREF="http://www.boost.org/">boost.org</A>
  578. mailing list. Some discussion of the implementation took place on the mailing
  579. list. In particular, Andrew D. Jewell pointed out the importance of ensuring
  580. that the risk of overflow was minimised, and provided overflow-free
  581. implementations of most of the basic operations. The name rational_cast was
  582. suggested by Kevlin Henney. Ed Brey provided invaluable comments - not least
  583. in pointing out some fairly stupid typing errors in the original code!</p>
  584. <p>David Abrahams contributed helpful feedback on the documentation.</p>
  585. <p>
  586. A long discussion of the merits of providing a conversion from floating
  587. point to rational took place on the boost list in November 2000. Key
  588. contributors included Reggie Seagraves, Lutz Kettner and Daniel Frey (although
  589. most of the boost list seemed to get involved at one point or another!). Even
  590. though the end result was a decision <em>not</em> to implement anything, the
  591. discussion was very valuable in understanding the issues.
  592. </p>
  593. <p>
  594. Stephen Silver contributed useful experience on using the rational class
  595. with a user-defined integer type.
  596. </p>
  597. <p>
  598. Nickolay Mladenov provided the current implementation of operator+= and
  599. operator-=.
  600. </p>
  601. <p>
  602. Discussion of the issues surrounding Koenig lookup and std::swap took place
  603. on the boost list in January 2001.
  604. </p>
  605. <p>
  606. Daryle Walker provided a Boolean conversion operator, so that a rational can
  607. be used in the same Boolean contexts as the built-in numeric types, in December
  608. 2005. He added the cross-instantiation constructor template in August 2013.
  609. </p>
  610. <p>
  611. July 2014: Updated numerator/denominator accessors to return values by constant
  612. reference: this gives a performance improvement when using with multiprecision (class) types.
  613. </p>
  614. <p>
  615. July 2014: Updated to use BOOST_THROW_EXCEPTION uniformly throughout.
  616. </p>
  617. <p>
  618. July 2014: Added support for C++11 constexpr constructors, plus tests to match.
  619. </p>
  620. <p>
  621. Nov 2014: Added support for gcd and lcm of rational numbers.
  622. </p>
  623. <p>
  624. Dec 2016: Reworked constructors and operators to prohibit narrowing implicit
  625. conversions, in particular accidental conversion from floating point types.
  626. </p>
  627. <p>
  628. Oct/Nov 2018: Add more constexpr.
  629. </p>
  630. <p>Revised July 14, 2017</p>
  631. <p>&copy; Copyright Paul Moore 1999-2001; &copy; Daryle Walker 2005, 2013.
  632. Permission to copy, use, modify, sell and distribute this document is granted
  633. provided this copyright notice appears in all copies. This document is provided
  634. &quot;as is&quot; without express or implied warranty, and with no claim as to
  635. its suitability for any purpose.</p>
  636. <!-- boostinspect:nolicense (can't find Paul Moore to change license) -->
  637. </body>
  638. </html>