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

Click here to view the latest version of this page.
PrevUpHomeNext
Real Number Generators (float_, double_, etc.)
Description

The real_generator can generate real numbers of arbitrary length and size limited by its template parameter, Num. The numeric base type Num can be a user defined numeric type such as fixed_point (fixed point reals) and bignum (unlimited precision numbers) if the type follows certain expression requirements (for more information about the requirements, see below).

Header
// forwards to <boost/spirit/home/karma/numeric/real.hpp>
#include <boost/spirit/include/karma_real.hpp>

Also, see Include Structure.

Namespace

Name

boost::spirit::lit // alias: boost::spirit::karma::lit

boost::spirit::float_ // alias: boost::spirit::karma::float_

boost::spirit::double_ // alias: boost::spirit::karma::double_

boost::spirit::long_double // alias: boost::spirit::karma::long_double

[Note] Note

lit is reused by the String Generators, the Character Generators, and the Numeric Generators. In general, a char generator is created when you pass in a character, a string generator is created when you pass in a string, and a numeric generator is created when you use a numeric literal.

Synopsis
template <typename Num, typename RealPolicies>
struct real_generator;
Template parameters

Parameter

Description

Default

Num

The type of the real number to generate.

double

RealPolicies

The policies to use while converting the real number.

real_policies<Num>

For more information about the type RealPolicies see below.

Model of

PrimitiveGenerator

Notation

num

Numeric literal, any real number value, or a Lazy Argument that evaluates to a real number value of type Num

Num

Type of num: any real number type

Expression Semantics

Semantics of an expression is defined only where it differs from, or is not defined in PrimitiveGenerator.

Expression

Semantics

lit(num)

Generate the real number literal num using the default formatting (no trailing zeros, fixed representation for numbers fabs(n) <= 1e5 && fabs(n) > 1e-3, scientific representation otherwise, 3 fractional digits, sign is only printed for negative literals). This generator never fails (unless the underlying output stream reports an error).

float_
double_
long_double

Generate the real number provided by a mandatory attribute using the default formatting (no trailing zeros, fixed representation for numbers fabs(n) <= 1e5 && fabs(n) > 1e-3, scientific representation otherwise, 3 fractional digits, sign is only printed for negative literals). This generator never fails (unless the underlying output stream reports an error).

float_(num)
double_(num)
long_double(num)

Generate the real point number provided by the immediate literal value the generator is initialized from using the default formatting (no trailing zeros, fixed representation for numbers fabs(n) <= 1e5 && fabs(n) > 1e-3, scientific representation otherwise, 3 fractional digits, sign is only printed for negative literals). If this generator has an associated attribute it succeeds only if the attribute is equal to the immediate literal (unless the underlying output stream reports an error). Otherwise this generator fails and does not generate any output.

All generators listed in the table above (except lit(num)) are predefined specializations of the real_generator<Num, RealPolicies> basic real number generator type described below. It is possible to directly use this type to create real number generators using a wide range of formatting options.

Expression

Semantics

real_generator<
    Num, RealPolicies
>()

Generate the real number of type Num provided by a mandatory attribute using the specified RealPolicies. This generator never fails (unless the underlying output stream reports an error).

real_generator<
    Num, RealPolicies
>()(num)

Generate the real number of type Num provided by the immediate literal value the generator is initialized from using the specified RealPolicies. If this generator has an associated attribute it succeeds only if the attribute is equal to the immediate literal (unless the underlying output stream reports an error). Otherwise this generator fails and does not generate any output.

Additional Requirements

The following list enumerates the requirements which must be met in order to use a certain type Num to instantiate a real_generator<Num, Policies>.

In order to be usable as the first template parameter for real_generator<> the type Num must have defined:

Attributes

Expression

Attribute

lit(num)

unused

float_

float, attribute is mandatory (otherwise compilation will fail)

float_(num)

float_, attribute is optional, if it is supplied, the generator compares the attribute with num and succeeds only if both are equal, failing otherwise.

double_

double, attribute is mandatory (otherwise compilation will fail)

double_(num)

double, attribute is optional, if it is supplied, the generator compares the attribute with num and succeeds only if both are equal, failing otherwise.

long_double

long double, attribute is mandatory (otherwise compilation will fail)

long_double(num)

long double, attribute is optional, if it is supplied, the generator compares the attribute with num and succeeds only if both are equal, failing otherwise.

real_generator<
    Num, Policies
>()

Num, attribute is mandatory (otherwise compilation will fail)

real_generator<
    Num, Policies
>()(num)

Num, attribute is optional, if it is supplied, the generator compares the attribute with num and succeeds only if both are equal, failing otherwise.

[Note] Note

In addition to their usual attribute of type Num all listed generators accept an instance of a boost::optional<Num> as well. If the boost::optional<> is initialized (holds a value) the generators behave as if their attribute was an instance of Num and emit the value stored in the boost::optional<>. Otherwise the generators will fail.

Real Number Formatting Policies

If special formatting of a real number is needed, overload the policy class real_policies<Num> and use it as a template parameter to the real_generator<> real number generator. For instance:

// define a new real number formatting policy
template <typename Num>
struct scientific_policy : real_policies<Num>
{
    // we want the numbers always to be in scientific format
    static int floatfield(Num n) { return fmtflags::scientific; }
};

// define a new generator type based on the new policy
typedef real_generator<double, scientific_policy<double> > science_type;
science_type const scientific = science_type();

// use the new generator 
generate(sink, science_type(), 1.0);  // will output: 1.0e00
generate(sink, scientific, 0.1);      // will output: 1.0e-01

The template parameter Num should be the type to be formatted using the overloaded policy type. At the same time Num will be used as the attribute type of the created real number generator.

Real Number Formatting Policy Expression Semantics

A real number formatting policy should expose the following variables and functions:

Expression

Description

template <typename Inserter
  , typename OutputIterator
  , typename Policies>
bool call (OutputIterator& sink, Num n
  , Policies const& p);

This is the main function used to generate the output for a real number. It is called by the real generator in order to perform the conversion. In theory all of the work can be implemented here, but the easiest way is to use existing functionality provided by the type specified by the template parameter Inserter. The default implementation of this functions is:

template <typename Inserter, typename OutputIterator
  , typename Policies>
static bool
call (OutputIterator& sink, Num n, Policies const& p)
{
    return Inserter::call_n(sink, n, p);
}

sink is the output iterator to use for generation

n is the real number to convert

p is the instance of the policy type used to instantiate this real number generator.

bool force_sign(Num n);

The default behavior is to not to require generating a sign. If the function force_sign() returns true, then all generated numbers will have a sign ('+' or '-', zeros will have a space instead of a sign).

n is the real number to output. This can be used to adjust the required behavior depending on the value of this number.

bool trailing_zeros(Num n);

Return whether trailing zero digits have to be emitted in the fractional part of the output. If set, this flag instructs the real number generator to emit trailing zeros up to the required precision digits (as returned by the precision() function).

n is the real number to output. This can be used to adjust the required behavior depending on the value of this number.

int floatfield(Num n);

Decide, which representation type to use in the generated output.

By default all numbers having an absolute value of zero or in between 0.001 and 100000 will be generated using the fixed format, all others will be generated using the scientific representation.

The trailing_zeros() can be used to force the output of trailing zeros in the fractional part up to the number of digits returned by the precision() member function. The default is not to generate the trailing zeros.

n is the real number to output. This can be used to adjust the formatting flags depending on the value of this number.

The return value has to be either fmtflags::scientific (generate real number values in scientific notation) or fmtflags::fixed (generate real number values in fixed-point notation).

unsigned precision(Num n);

Return the maximum number of decimal digits to generate in the fractional part of the output.

n is the real number to output. This can be used to adjust the required precision depending on the value of this number. If the trailing zeros flag is specified the fractional part of the output will be 'filled' with zeros, if appropriate.

Note: If the trailing_zeros flag is not in effect additional semantics apply. See the description for the fraction_part() function below. Moreover, this precision will be limited to the value of std::numeric_limits<T>::digits10 + 1.

template <bool ForceSign, 
    typename OutputIterator>
bool integer_part(OutputIterator& sink
  , Num n, bool sign, bool force_sign);

This function is called to generate the integer part of the real number.

sink is the output iterator to use for generation

n is the absolute value of the integer part of the real number to convert (always non-negative)

sign is the sign of the overall real number to convert.

force_sign is a flag indicating whether a sign has to be generated even for non-negative numbers (this is the same as has been returned from the function force_sign() described above)

The return value defines the outcome of the whole generator. If it is false, no further output is generated, immediately returning false from the calling real_generator as well. If it is true, normal output generation continues.

template <typename OutputIterator>
bool dot(OutputIterator& sink, Num n,
  unsigned precision);

This function is called to generate the decimal point.

sink is the output iterator to use for generation

n is the fractional part of the real number to convert. Note that this number is scaled such, that it represents the number of units which correspond to the value returned from the precision() function earlier. I.e. a fractional part of 0.01234 is represented as 1234 when the function precision() returned 5.

precision is the number of digits to emit as returned by the function precision() described above

This is given to allow to decide, whether a decimal point has to be generated at all.

Note: If the trailing_zeros flag is not in effect additional comments apply. See the description for the fraction_part() function below.

The return value defines the outcome of the whole generator. If it is false, no further output is generated, immediately returning false from the calling real_generator as well. If it is true, normal output generation continues.

template <typename OutputIterator>
bool fraction_part(OutputIterator& sink, Num n
  , unsigned adjprec, unsigned precision);

This function is called to generate the fractional part of the number.

sink is the output iterator to use for generation

n is the fractional part of the real number to convert. Note that this number is scaled such, that it represents the number of units which correspond to the value returned from the precision() function earlier. I.e. a fractional part of 0.01234 is represented as 1234 when the function precision() returned 5.

adjprec is the corrected number of digits to emit (see note below)

precision is the number of digits to emit as returned by the function precision() described above

Note: If trailing_zeros() returns false the adjprec parameter will have been corrected from the value the precision() function returned earlier (defining the maximal number of fractional digits) in the sense, that it takes into account trailing zeros. I.e. a real number 0.0123 and a value of 5 returned from precision() will result in:

trailing_zeros() returned false: n will be 123, and adjprec will be 4 (as we need to print 0123)

trailing_zeros() returned true: n will be 1230, and adjprec will be 5 (as we need to print 01230)

The missing preceding zeros in the fractional part have to be supplied by the implementation of this policy function.

The return value defines the outcome of the whole generator. If it is false, no further output is generated, immediately returning false from the calling real_generator as well. If it is true, normal output generation continues.

template <typename CharEncoding, 
    typename Tag, typename OutputIterator>
bool exponent(
    OutputIterator& sink, long n);

This function is called to generate the exponential part of the number (this is called only if the floatfield() function returned the fmtflags::scientific flag).

sink is the output iterator to use for generation

n is the (signed) exponential part of the real number to convert.

The template parameters CharEncoding and Tag are either of the type unused_type or describe the character class and conversion to be applied to any output possibly influenced by either the lower[] or upper[] directives.

The return value defines the outcome of the whole generator. If it is false, no further output is generated, immediately returning false from the calling real_generator as well. If it is true, normal output generation continues.

template <typename CharEncoding
  , typename Tag, typename OutputIterator>
bool nan (OutputIterator& sink, Num n
  , bool force_sign);

This function is called whenever the number to print is a non-normal real number of type NaN.

sink is the output iterator to use for generation

n is the (signed) real number to convert

force_sign is a flag indicating whether a sign has to be generated even for non-negative numbers (this is the same as has been returned from the function force_sign() described above)

The template parameters CharEncoding and Tag are either of the type unused_type or describe the character class and conversion to be applied to any output possibly influenced by either the lower[] or upper[] directives.

The return value defines the outcome of the whole generator. If it is false, no further output is generated, immediately returning false from the calling real_generator as well. If it is true, normal output generation continues.

template <typename CharEncoding
  , typename Tag, typename OutputIterator>
bool inf (OutputIterator& sink, Num n
  , bool force_sign);

This function is called whenever the number to print is a non-normal real number of type Inf.

sink is the output iterator to use for generation

n is the (signed) real number to convert

force_sign is a flag indicating whether a sign has to be generated even for non-negative numbers (this is the same as has been returned from the function force_sign() described above)

The template parameters CharEncoding and Tag are either of the type unused_type or describe the character class and conversion to be applied to any output possibly influenced by either the lower[] or upper[] directives.

The return value defines the outcome of the whole generator. If it is false, no further output is generated, immediately returning false from the calling real_generator as well. If it is true, normal output generation continues.

[Tip] Tip

The easiest way to implement a proper real number formatting policy is to derive a new type from the the type real_policies<> while overriding the aspects of the formatting which need to be changed.

Complexity

O(N), where N is the number of digits needed to represent the generated real number.

Example
[Note] Note

The test harness for the example(s) below is presented in the Basics Examples section.

Some includes:

#include <boost/spirit/include/karma.hpp>
#include <boost/spirit/include/phoenix_core.hpp>
#include <boost/spirit/include/phoenix_operator.hpp>
#include <boost/fusion/include/std_pair.hpp>
#include <iostream>
#include <string>

Some using declarations:

using boost::spirit::karma::double_;
using boost::spirit::karma::lit;

Basic usage of an double_ generator:

test_generator("2.0", lit(2.0));
test_generator("2.0", double_(2));
test_generator_attr("2.0", double_(2.0), 2.0);
test_generator_attr("", double_(2.0), 3.0);    // fails (as 2.0 != 3.0)!
test_generator_attr("-2.0", double_, -2.0);

test_generator_attr("1.234e05", double_, 1234.0e2);
test_generator_attr("1.234e-06", double_, 0.000001234);


PrevUpHomeNext