scientific computation (more)

W

Wing

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.
 
S

Stuart Redmann

Wing said:
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
 

Ask a Question

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

You'll need to choose a username for the site, which only take a couple of moments. After that, you can post your question and our members will help you out.

Ask a Question

Members online

Forum statistics

Threads
473,744
Messages
2,569,480
Members
44,900
Latest member
Nell636132

Latest Threads

Top