[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |
4.6 Numbers
For storing numerical things, GiNaC uses Bruno Haible's library CLN. The classes therein serve as foundation classes for GiNaC. CLN stands for Class Library for Numbers or alternatively for Common Lisp Numbers. In order to find out more about CLN's internals, the reader is referred to the documentation of that library. See (cln)Introduction, for more information. Suffice to say that it is by itself build on top of another library, the GNU Multiple Precision library GMP, which is an extremely fast library for arbitrary long integers and rationals as well as arbitrary precision floating point numbers. It is very commonly used by several popular cryptographic applications. CLN extends GMP by several useful things: First, it introduces the complex number field over either reals (i.e. floating point numbers with arbitrary precision) or rationals. Second, it automatically converts rationals to integers if the denominator is unity and complex numbers to real numbers if the imaginary part vanishes and also correctly treats algebraic functions. Third it provides good implementations of state-of-the-art algorithms for all trigonometric and hyperbolic functions as well as for calculation of some useful constants.
The user can construct an object of class numeric
in several
ways. The following example shows the four most important constructors.
It uses construction from C-integer, construction of fractions from two
integers, construction from C-float and construction from a string:
#include <iostream> #include <ginac/ginac.h> using namespace GiNaC; int main() { numeric two = 2; // exact integer 2 numeric r(2,3); // exact fraction 2/3 numeric e(2.71828); // floating point number numeric p = "3.14159265358979323846"; // constructor from string // Trott's constant in scientific notation: numeric trott("1.0841015122311136151E-2"); std::cout << two*p << std::endl; // floating point 6.283... ... |
The imaginary unit in GiNaC is a predefined numeric
object with the
name I
:
... numeric z1 = 2-3*I; // exact complex number 2-3i numeric z2 = 5.9+1.6*I; // complex floating point number } |
It may be tempting to construct fractions by writing numeric r(3/2)
.
This would, however, call C's built-in operator /
for integers
first and result in a numeric holding a plain integer 1. Never
use the operator /
on integers unless you know exactly what you
are doing! Use the constructor from two integers instead, as shown in
the example above. Writing numeric(1)/2
may look funny but works
also.
We have seen now the distinction between exact numbers and floating
point numbers. Clearly, the user should never have to worry about
dynamically created exact numbers, since their `exactness' always
determines how they ought to be handled, i.e. how `long' they are. The
situation is different for floating point numbers. Their accuracy is
controlled by one global variable, called Digits
. (For
those readers who know about Maple: it behaves very much like Maple's
Digits
). All objects of class numeric that are constructed from
then on will be stored with a precision matching that number of decimal
digits:
#include <iostream> #include <ginac/ginac.h> using namespace std; using namespace GiNaC; void foo() { numeric three(3.0), one(1.0); numeric x = one/three; cout << "in " << Digits << " digits:" << endl; cout << x << endl; cout << Pi.evalf() << endl; } int main() { foo(); Digits = 60; foo(); return 0; } |
The above example prints the following output to screen:
in 17 digits: 0.33333333333333333334 3.1415926535897932385 in 60 digits: 0.33333333333333333333333333333333333333333333333333333333333333333334 3.1415926535897932384626433832795028841971693993751058209749445923078 |
Note that the last number is not necessarily rounded as you would naively expect it to be rounded in the decimal system. But note also, that in both cases you got a couple of extra digits. This is because numbers are internally stored by CLN as chunks of binary digits in order to match your machine's word size and to not waste precision. Thus, on architectures with different word size, the above output might even differ with regard to actually computed digits.
It should be clear that objects of class numeric
should be used
for constructing numbers or for doing arithmetic with them. The objects
one deals with most of the time are the polymorphic expressions ex
.
[ < ] | [ > ] | [ << ] | [ Up ] | [ >> ] | [Top] | [Contents] | [Index] | [ ? ] |