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