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 Numbers (float_, double_, etc.)
Description

The real_parser can parse real numbers of arbitrary length and size limited by its template parameter, T. The numeric base type T can be a user defined numeric type such as fixed_point (fixed point reals) and bignum (unlimited precision numbers) as long as the type follows certain expression requirements (documented below).

Header
// forwards to <boost/spirit/home/qi/numeric/real.hpp>
#include <boost/spirit/include/qi_real.hpp>

Also, see Include Structure.

Namespace

Name

boost::spirit::float_ // alias: boost::spirit::qi::float_

boost::spirit::double_ // alias: boost::spirit::qi::double_

boost::spirit::long_double // alias: boost::spirit::qi::long_double

Synopsis
template <typename T, typename RealPolicies>
struct real_parser;
Template parameters

Parameter

Description

Default

T

The numeric base type of the numeric parser.

none

RealPolicies

Policies control the parser's behavior.

real_policies<T>

Model of

PrimitiveParser

Notation

NP

An instance of real_parser (type).

RP

A RealPolicies (type).

n

An object of T, the numeric base type.

exp

A int exponent.

b

A bool flag.

f, l

ForwardIterator. first/last iterator pair.

Expression Semantics

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

Expression

Semantics

NP()

Instantiate and (default) construct an real_parser

float_

Create an real_parser<float, real_policies<T> >

double_

Create an real_parser<double, real_policies<T> >

long_double

Create an real_parser<long double, real_policies<T> >

Attributes

T, The numeric base type of the numeric parser.

Complexity

O(N), where N is the number of characters (including the digits, exponent, sign, etc.) being parsed.

Minimum Expression Requirements for T

The numeric base type, T, the minimum expression requirements listed below must be valid. Take note that additional requirements may be imposed by custom policies.

Expression

Semantics

T()

Default construct.

T(0)

Construct from an int.

n + n

Addition.

n - n

Subtraction.

n * n

Multiplication.

std::numeric_limits<T>::is_bounded

true or false if T bounded.

std::numeric_limits<T>::digits

Maximum Digits for T, radix digits. Required only if T is bounded.

std::numeric_limits<T>::digits10

Maximum Digits for T, base 10. Required only if T is bounded.

std::numeric_limits<T>::max()

Maximum value for T. Required only if T is bounded.

std::numeric_limits<T>::min()

Minimum value for T. Required only if T is bounded.

boost::spirit::traits::scale(exp, n)

Multiply n by 10^exp. Default implementation is provided for float, double and long double.

boost::spirit::traits::negate(b, n)

Negate n if b is true. Default implementation is provided for float, double and long double.

boost::spirit::traits::is_equal_to_one(n)

Return true if n is equal to 1.0. Default implementation is provided for float, double and long double.

[Note] Note

The additional spirit real number traits above are provided to allow custom implementations to implement efficient real number parsers. For example, for certain custom real numbers, scaling to a base 10 exponent is a very cheap operation.

RealPolicies

The RealPolicies template parameter is a class that groups all the policies that control the parser's behavior. Policies control the real number parsers' behavior.

The default is real_policies<T>. The default is provided to take care of the most common case (there are many ways to represent, and hence parse, real numbers). In most cases, the default policies are sufficient and can be used straight out of the box. They are designed to parse C/C++ style floating point numbers of the form nnn.fff.Eeee where nnn is the whole number part, fff is the fractional part, E is 'e' or 'E' and eee is the exponent optionally preceded by '-' or '+' with the additional detection of NaN and Inf as mandated by the C99 Standard and proposed for inclusion into the C++0x Standard: nan, nan(...), inf and infinity (the matching is case-insensitive). This corresponds to the following grammar:

sign
    =   lit('+') | '-'
    ;

nan 
    =   -lit("1.0#") >> no_case["nan"] 
        >> -('(' >> *(char_ - ')') >> ')')
    ;
    
inf
    =   no_case[lit("inf") >> -lit("inity")]
    ;

floating_literal
    =   -sign >>
        (       nan
            |   inf
            |   fractional_constant >> !exponent_part
            |  +digit >> exponent_part
        )
    ;

fractional_constant
    =  *digit >> '.' >> +digit
    |  +digit >> -lit('.')
    ;

exponent_part
    =   (lit('e') | 'E') >> -sign >> +digit
    ;

There are four RealPolicies pre-defined for immediate use:

Table 4. Predefined Policies

Policies

Description

ureal_policies<double> >

Without sign.

real_policies<double> >

With sign.

strict_ureal_policies<double> >

Without sign, dot required.

strict_real_policies<double> >

With sign, dot required.


[Note] Note

Integers are considered a subset of real numbers, so for instance, double_ recognizes integer numbers (without a dot) just as well. To avoid this ambiguity, strict_ureal_policies and strict_real_policies require a dot to be present for a number to be considered a successful match.

RealPolicies Expression Requirements

For models of RealPolicies the following expressions must be valid:

Expression

Semantics

RP::allow_leading_dot

Allow leading dot.

RP::allow_trailing_dot

Allow trailing dot.

RP::expect_dot

Require a dot.

RP::parse_sign(f, l)

Parse the prefix sign (e.g. '-'). Return true if successful, otherwise false.

RP::parse_n(f, l, n)

Parse the integer at the left of the decimal point. Return true if successful, otherwise false. If successful, place the result into n.

RP::parse_dot(f, l)

Parse the decimal point. Return true if successful, otherwise false.

RP::parse_frac_n(f, l, n)

Parse the fraction after the decimal point. Return true if successful, otherwise false. If successful, place the result into n.

RP::parse_exp(f, l)

Parse the exponent prefix (e.g. 'e'). Return true if successful, otherwise false.

RP::parse_exp_n(f, l, n)

Parse the actual exponent. Return true if successful, otherwise false. If successful, place the result into n.

RP::parse_nan(f, l, n)

Parse a NaN. Return true if successful, otherwise false. If successful, place the result into n.

RP::parse_inf(f, l, n)

Parse an Inf. Return true if successful, otherwise false. If successful, place the result into n.

The parse_nan and parse_inf functions get called whenever:

a number to parse does not start with a digit (after having successfully parsed an optional sign)

or

after a real number of the value 1 (having no exponential part and a fractional part value of 0) has been parsed.

The first call recognizes representations of NaN or Inf starting with a non-digit character (such as NaN, Inf, QNaN etc.). The second call recognizes representation formats starting with a 1.0 (such as "1.0#NAN" or "1.0#INF" etc.).

The functions should return true if a Nan or Inf has been found. In this case the attribute n should be set to the matched value (NaN or Inf). The optional sign will be automatically applied afterwards.

RealPolicies Specializations

The easiest way to implement a proper real parsing policy is to derive a new type from the the type real_policies while overriding the aspects of the parsing which need to be changed. For example, here's the implementation of the pre-defined strict_real_policies:

template <typename T>
struct strict_real_policies : real_policies<T>
{
    static bool const expect_dot = true;
};
Example
[Note] Note

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

Some using declarations:

using boost::spirit::qi::double_;
using boost::spirit::qi::real_parser;

Basic real number parsing:

test_parser("+12345e6", double_);

A custom real number policy:

///////////////////////////////////////////////////////////////////////////////
//  These policies can be used to parse thousand separated
//  numbers with at most 2 decimal digits after the decimal
//  point. e.g. 123,456,789.01
///////////////////////////////////////////////////////////////////////////////
template <typename T>
struct ts_real_policies : boost::spirit::qi::ureal_policies<T>
{
    //  2 decimal places Max
    template <typename Iterator, typename Attribute>
    static bool
    parse_frac_n(Iterator& first, Iterator const& last, Attribute& attr)
    {
        return boost::spirit::qi::
            extract_uint<T, 10, 1, 2, true>::call(first, last, attr);
    }

    //  No exponent
    template <typename Iterator>
    static bool
    parse_exp(Iterator&, Iterator const&)
    {
        return false;
    }

    //  No exponent
    template <typename Iterator, typename Attribute>
    static bool
    parse_exp_n(Iterator&, Iterator const&, Attribute&)
    {
        return false;
    }

    //  Thousands separated numbers
    template <typename Iterator, typename Attribute>
    static bool
    parse_n(Iterator& first, Iterator const& last, Attribute& attr)
    {
        using boost::spirit::qi::uint_parser;
        namespace qi = boost::spirit::qi;

        uint_parser<unsigned, 10, 1, 3> uint3;
        uint_parser<unsigned, 10, 3, 3> uint3_3;

        T result = 0;
        if (parse(first, last, uint3, result))
        {
            bool hit = false;
            T n;
            Iterator save = first;

            while (qi::parse(first, last, ',') && qi::parse(first, last, uint3_3, n))
            {
                result = result * 1000 + n;
                save = first;
                hit = true;
            }

            first = save;
            if (hit)
                attr = result;
            return hit;
        }
        return false;
    }
};

And its use:

real_parser<double, ts_real_policies<double> > ts_real;
test_parser("123,456,789.01", ts_real);


PrevUpHomeNext