Here is a collection of basic operations available for rational values;
see also the more advanced functions in NumTheory
.
The usual arithmetic operations are available with standard C++
syntax. The type BigRat
is provided for convenience of
representing rational values rather than for rapid computation; the
native GMP operations may be noticeably faster.
There is an important exception to the natural syntax: ^
does not
denote exponentiation; you must use the function power
instead.
We have chosen not to define operator^
to perform exponentiation
because it is too easy to write misleading code: for instance,
a*b^2
is interpreted by the compiler as (a*b)^2
. There is no
way to make the C++ compiler use the expected interpretation.
Arithmetic may also be performed between a BigRat
and a machine
integer or a BigInt
. The result is always of type BigRat
(even if the value turns out to be an integer). Do remember, though,
that operations between two machine integers are handled directly by
C++, and problems of overflow can occur.
NOTE: similar to operations on BigInt
-- see BigIntOps
+
the sum
-
the difference
*
the product
/
quotient
=
assignment
+=
, -=
, *=
, /=
-- definitions as expected; LHS must be of type BigRat
==
, !=
<
, <=
, >
, >=
-- comparison (using the normal arithmetic ordering)
-- see also the cmp
function below.
++
, --
(prefix, e.g. ++a
) use these if you can
++
, --
(postfix, e.g. a++
) avoid these if you can, as they create temporaries
IsZero(q)
-- true iff q
is zero
IsOne(q)
-- true iff q
is 1
IsMinusOne(q)
-- true iff q
is -1
IsOneNum(q)
-- true iff num(q)
is 1
IsOneDen(q)
-- true iff den(q)
is 1
IsPowerOf2(q)
-- true iff q
is a power of 2
sign(q)
-- gives -1 (machine integer) to mean q
is negative,
0 (machine integer) to mean q
is zero,
+1 (machine integer) to mean q
is positive.
power(a, b)
-- returns a
to the power b
(result is always a BigRat
)
cmp(a,b)
-- returns an int
which is < 0
if a < b
, or == 0
if a == b
, or > 0
if a > b
.
CmpAbs(a,b)
-- equivalent to cmp(abs(a),abs(b))
abs(q)
-- gives the absolute value of q
floor(q)
-- returns a BigInt
for the greatest integer <= q
ceil(q)
-- returns a BigInt
for the least integer >= q
round(q)
-- returns a BigInt
which is the nearest to q
(halves round the same way as in RoundDiv
, see BigIntOps
)
num(q)
-- returns a BigInt
which is the numerator of q
den(q)
-- returns a positive BigInt
which is the denominator of q
CommonDenom(v)
-- returns least (positive) common denominator for a vector of BigRat
log(q)
-- returns a double whose value is (approx) the natural logarithm of q
; error if `` q <= 0``.
LogAbs(q)
-- equiv to log(abs(q))
FloorLog2(q) -- same as ``FloorLogBase(q,2)
FloorLog10(q) -- same as ``FloorLogBase(q,10)
FloorLogBase(q,base)
-- returns largest integer k
such that power(base,k) <= abs(q)
; error if base < 2
mantissa(q)
-- returns a double
between 0.5 and 1 (excluded)
exponent(q)
--
Only for BigInt
mantissa(N)
-- N
represented as a floating-point number.
If N
is zero, produces 0.0.
If N>0
, produces a value between 0.5 and 0.999...;
otherwise (when N<0
) a value between -0.5 and -0.999...
The bits of the floating point result are the topmost
bits of the binary representation of N
.
exponent(N)
-- result is a long
whose value is the least integer e such that
2^e > abs(n). If N
is zero, result is zero.
To sum many rationals use a SumBigRat
object.
This class is not thread-safe.
Let n
be an integer, q
be a BigRat
, and SBR
be a SumBigRat
object.
SumBigRat()
-- create a SumBigRat
object with value 0
SBR += n
-- accumulate n
into the sum inside SBR
SBR += q
-- accumulate q
into the sum inside SBR
total(SBR)
-- return the sum of the values accumulated
SBR.myTotal()
-- same as total(SBR)
Currently there is no operator-=
; should there be?
Most impls are very simple (since GMP does all the real work).
Impl of FloorLogBase
is ugly!
The SizeInBase(N, b)
has been removed: use 1+FloorLogBase(N)
instead.
There are some NYI functions!
2023
SumBigRat
2018
BigRat