scientific computation (more)

Discussion in 'C++' started by Wing, Sep 26, 2006.

  1. Wing

    Wing Guest

    Thanks for those who answered my question previously.

    Everytime I want to output high precision numbers, I use the following
    code:

    cout << setprecision (9) << f << endl;

    where f is some double number.

    However, I don't want to add "setprecision (9)" in every "cout" and
    "iofstream" in order to output/input high precision number, because I
    need to modify my codes substantially in this case.

    What can I do such that my program can output high precision numbers
    without modifying the codes substantially?

    Thanks.
     
    Wing, Sep 26, 2006
    #1
    1. Advertising

  2. Wing wrote:

    > Thanks for those who answered my question previously.
    >
    > Everytime I want to output high precision numbers, I use the following
    > code:
    >
    > cout << setprecision (9) << f << endl;
    >
    > where f is some double number.
    >
    > However, I don't want to add "setprecision (9)" in every "cout" and
    > "iofstream" in order to output/input high precision number, because I
    > need to modify my codes substantially in this case.
    >
    > What can I do such that my program can output high precision numbers
    > without modifying the codes substantially?
    >
    > Thanks.
    >


    You could define your own version of cout in the following way:

    #include <iostream>
    #include <ostream>
    #include <iomanip>

    class CCustomOutputStream
    {
    public:
    CCustomOutputStream (std::eek:stream& p_refUnderlyingOStream, int
    p_iDefaultPrecision)
    : m_pInternalOStream (&p_refUnderlyingOStream),
    m_iDefaultPrecision (p_iDefaultPrecision),
    m_NextPrecision (-1)
    {
    if (p_iDefaultPrecision < 0 || p_iDefaultPrecision > 20)
    throw exception ();
    }

    CCustomOutputStream& operator<< (std::eek:stream& (__cdecl
    *_F)(std::eek:stream&))
    {
    // Invoke the passed I/O function for the internal stream.
    _F (*m_pInternalOStream);
    return *this;
    }
    CCustomOutputStream& operator<< (std::ios& (__cdecl *_F)(std::ios&))
    {
    // Invoke the passed I/O function for the internal stream.
    _F (*m_pInternalOStream);
    return *this;
    }

    /*! \brief This method can be used to access the internal stream.
    */
    std::eek:stream* GetInternalStream ()
    {
    return m_pInternalOStream;
    }

    protected:
    /*! \brief The internal output stream.
    */
    std::eek:stream* m_pInternalOStream;

    /*! \brief If the user has provided a precision, we will use this
    * value for the next floating point value.
    * If this value is -1, we should use the default precision for the
    * next floating point value.
    */
    int m_NextPrecision;

    /*! \brief The default precision that should be used for floating
    * point values.
    */
    int m_iDefaultPrecision;

    public:
    /*! \brief This is how outputting data is done in general: Just
    * forward the call to the internal stream.
    */
    template <class T>
    CCustomOutputStream& operator<< (T p_RHS)
    {
    // Forward the call to the internal output stream.
    *m_pInternalOStream << p_RHS;
    return *this;
    }

    /*! \brief Template specialization for the setprecision manipulator.
    */
    template<>
    CCustomOutputStream& operator<< (std::_Smanip<std::streamsize>
    p_Manipulator)
    {
    // If the manipulator function is sbfun (the function that sets
    // the precision of a given stream),
    // we remember the argument, so that the next print of a floating
    // point variable is done with this
    // precision (Had we not remembered this, we would print the next
    // floating point value with our internal
    // default precision.
    if (p_Manipulator._Pf == std::setprecision (0)._Pf)
    {
    m_NextPrecision = p_Manipulator._Manarg;
    }
    return *this;
    }

    /*! \brief Template specialization for floating point values.
    */
    template<>
    CCustomOutputStream& operator<< (float p_RHS)
    {
    // If the precision was explicitely set by a previous call
    // to setprecision, we use this precision. Else
    // we use the standard precision of this custom stream.
    if (m_NextPrecision > 0)
    {
    m_pInternalOStream->precision (m_NextPrecision);
    m_NextPrecision = -1;
    }
    else
    m_pInternalOStream->precision (m_iDefaultPrecision);

    // Print the float value with the set precision.
    *m_pInternalOStream << p_RHS;
    return *this;
    }

    template<>
    CCustomOutputStream& operator<< (double p_RHS)
    {
    // If the precision was explicitely set by a previous call to
    // setprecision, we use this precision. Else
    // we use the standard precision of this custom stream.
    if (m_NextPrecision > 0)
    {
    m_pInternalOStream->precision (m_NextPrecision);
    m_NextPrecision = -1;
    }
    else
    m_pInternalOStream->precision (m_iDefaultPrecision);

    // Print the float value with the set precision.
    *m_pInternalOStream << p_RHS;
    return *this;
    }
    };

    CCustomOutputStream Mycout (std::cout, 7);

    int main ()
    {
    Mycout << "Pi with default precision: "
    << 3.1415926535897 << std::endl
    << "Pi with precision 2: "
    << std::setprecision (2) << 3.1415926535897 << std::endl
    << "Pi with default precision: "
    << 3.1415926535897 << std::endl;

    return 0;
    }

    All you have to do is replacing of cout by Mycout (which can be done
    with replace-in-files tools). If you use output streams to files, you
    have to create one custom output stream for each such stream. If you use
    the internals of a stream (like failbit), you may need to add these
    features to CCustomOutputStream, so that you don't have to retrieve the
    internal stream every time. CCustomOutputStream is also not a template
    that can work with UNICODE strings (I didn't want to spend to much time
    on this example).

    Regards,
    Stuart
     
    Stuart Redmann, Sep 26, 2006
    #2
    1. Advertising

Want to reply to this thread or ask your own question?

It takes just 2 minutes to sign up (and it's free!). Just click the sign up button to choose a username and then you can ask your own questions on the forum.
Similar Threads
  1. Michael Tobis

    Python advocacy in scientific computation

    Michael Tobis, Feb 14, 2006, in forum: Python
    Replies:
    56
    Views:
    1,120
    Philip Austin
    Mar 9, 2006
  2. David Treadwell

    Re: Python advocacy in scientific computation

    David Treadwell, Mar 4, 2006, in forum: Python
    Replies:
    2
    Views:
    325
    sturlamolden
    Mar 5, 2006
  3. David Treadwell

    Re: Python advocacy in scientific computation

    David Treadwell, Mar 4, 2006, in forum: Python
    Replies:
    5
    Views:
    332
    Dennis Lee Bieber
    Mar 5, 2006
  4. Wing

    scientific computation

    Wing, Sep 25, 2006, in forum: C++
    Replies:
    3
    Views:
    320
    Marcus Kwok
    Sep 25, 2006
  5. asdf

    scientific computation

    asdf, Oct 10, 2006, in forum: C++
    Replies:
    2
    Views:
    550
    Victor Bazarov
    Oct 10, 2006
Loading...

Share This Page