punto numeros numericos notaciĆ³n normalizada norma metodos mantisa informatica flotante exponente exceso ejemplos coma c++ floating-point cout ostream

c++ - numeros - punto flotante ejemplos



Formato de punto flotante para std:: ostream (6)

En general, desea evitar especificar cosas como 11 y 6 en el punto de salida. Eso es un marcado físico, y quieres un marcado lógico; por ejemplo, pressure o volume . De esta forma, usted define en un solo lugar cómo se formatea la presión o el volumen, y si ese formato cambia, no tiene que buscar en el programa para encontrar dónde cambiar el formato (y accidentalmente cambiar el formato de otra cosa) . En C ++, esto se hace definiendo un manipulador, que establece las diversas opciones de formato y, preferiblemente, las restaura al final de la expresión completa. Entonces terminas escribiendo cosas como:

std::cout << pressure << my_double;

Aunque definitivamente no lo usaría en el código de producción, he encontrado que el siguiente formateador FFmt útil para trabajos rápidos:

class FFmt : public StateSavingManip { public: explicit FFmt( int width, int prec = 6, std::ios::fmtflags additionalFlags = static_cast<std::ios::fmtflags>(), char fill = '' '' ); protected: virtual void setState( std::ios& targetStream ) const; private: int myWidth; int myPrec; std::ios::fmtflags myFlags; char myFill; }; FFmt::FFmt( int width, int prec, std::ios::fmtflags additionalFlags, char fill ) : myWidth( width ) , myPrec( prec ) , myFlags( additionalFlags ) , myFill( fill ) { myFlags &= ~ std::ios::floatfield myFlags |= std::ios::fixed if ( isdigit( static_cast< unsigned char >( fill ) ) && (myFlags & std::ios::adjustfield) == 0 ) { myFlags |= std::ios::internal } } void FFmt::setState( std::ios& targetStream ) const { targetStream.flags( myFlags ) targetStream.width( myWidth ) targetStream.precision( myPrec ) targetStream.fill( myFill ) }

Esto permite escribir cosas como:

std::cout << FFmt( 11, 6 ) << my_double;

Y para el registro:

class StateSavingManip { public: StateSavingManip( StateSavingManip const& other ); virtual ~StateSavingManip(); void operator()( std::ios& stream ) const; protected: StateSavingManip(); private: virtual void setState( std::ios& stream ) const = 0; private: StateSavingManip& operator=( StateSavingManip const& ); private: mutable std::ios* myStream; mutable std::ios::fmtflags mySavedFlags; mutable int mySavedPrec; mutable char mySavedFill; }; inline std::ostream& operator<<( std::ostream& out, StateSavingManip const& manip ) { manip( out ); return out; } inline std::istream& operator>>( std::istream& in, StateSavingManip const& manip ) { manip( in ); return in; }

StateSavingManip.cc:

namespace { // We maintain the value returned by ios::xalloc() + 1, and not // the value itself. The actual value may be zero, and we need // to be able to distinguish it from the 0 resulting from 0 // initialization. The function getXAlloc() returns this value // -1, so we add one in the initialization. int getXAlloc(); int ourXAlloc = getXAlloc() + 1; int getXAlloc() { if ( ourXAlloc == 0 ) { ourXAlloc = std::ios::xalloc() + 1; assert( ourXAlloc != 0 ); } return ourXAlloc - 1; } } StateSavingManip::StateSavingManip() : myStream( NULL ) { } StateSavingManip::StateSavingManip( StateSavingManip const& other ) { assert( other.myStream == NULL ); } StateSavingManip::~StateSavingManip() { if ( myStream != NULL ) { myStream->flags( mySavedFlags ); myStream->precision( mySavedPrec ); myStream->fill( mySavedFill ); myStream->pword( getXAlloc() ) = NULL; } } void StateSavingManip::operator()( std::ios& stream ) const { void*& backptr = stream.pword( getXAlloc() ); if ( backptr == NULL ) { backptr = const_cast< StateSavingManip* >( this ); myStream = &stream; mySavedFlags = stream.flags(); mySavedPrec = stream.precision(); mySavedFill = stream.fill(); } setState( stream ); }

¿Cómo hago lo siguiente con std :: cout?

double my_double = 42.0; char str[12]; printf_s("%11.6lf", my_double); // Prints " 42.000000"

Estoy a punto de darme por vencido y usar sprintf_s.

De manera más general, ¿dónde puedo encontrar una referencia en el formato std :: ostream que enumera todo en un solo lugar, en lugar de extenderlo todo en un largo tutorial?

EDITAR 21 de diciembre de 2017 - Ver mi respuesta a continuación. Utiliza funciones que no estaban disponibles cuando hice esta pregunta en 2012.


Para los futuros visitantes que prefieran las especificaciones de formato de estilo de impresión real con std :: ostream, aquí hay otra variación, basada en la excelente publicación de Martin York en otra pregunta de SO: https://.com/a/535636 :

#include <iostream> #include <iomanip> #include <stdio.h> //snprintf class FMT { public: explicit FMT(const char* fmt): m_fmt(fmt) {} private: class fmter //actual worker class { public: explicit fmter(std::ostream& strm, const FMT& fmt): m_strm(strm), m_fmt(fmt.m_fmt) {} //output next object (any type) to stream: template<typename TYPE> std::ostream& operator<<(const TYPE& value) { // return m_strm << "FMT(" << m_fmt << "," << value << ")"; char buf[40]; //enlarge as needed snprintf(buf, sizeof(buf), m_fmt, value); return m_strm << buf; } private: std::ostream& m_strm; const char* m_fmt; }; const char* m_fmt; //save fmt string for inner class //kludge: return derived stream to allow operator overloading: friend FMT::fmter operator<<(std::ostream& strm, const FMT& fmt) { return FMT::fmter(strm, fmt); } };

ejemplo de uso:

double my_double = 42.0; cout << FMT("%11.6f") << my_double << "more stuff/n";

o incluso:

int val = 42; cout << val << " in hex is " << FMT(" 0x%x") << val << "/n";


soy yo, el OP, Jive Dadson, cinco años después. C ++ 17 se está convirtiendo en una realidad.

El advenimiento de los parámetros de plantilla variados con reenvío perfecto ha hecho la vida mucho más simple. La locura encadenada de ostream << y boost :: format% se puede prescindir. La función oprintf a continuación completa la factura. Trabajo en progreso. Siéntete libre de avisar sobre el manejo de errores, etc ...

#include <iostream> #include <string.h> #include <stdio.h> #include <string_view> namespace dj { template<class Out, class... Args> Out& oprintf(Out &out, const std::string_view &fmt, Args&&... args) { const int sz = 512; char buffer[sz]; int cx = snprintf(buffer, sz, fmt.data(), std::forward<Args>(args)...); if (cx >= 0 && cx < sz) { return out.write(buffer, cx); } else if (cx > 0) { // Big output std::string buff2; buff2.resize(cx + 1); snprintf(buff2.data(), cx, fmt.data(), std::forward<Args>(args)...); return out.write(buff2.data(), cx); } else { // Throw? return out; } } } int main() { const double my_double = 42.0; dj::oprintf(std::cout, "%s %11.6lf/n", "My double ", my_double); return 0; }


#include <iostream> #include <iomanip> int main() { double my_double = 42.0; std::cout << std::fixed << std::setw(11) << std::setprecision(6) << my_double << std::endl; return 0; }


std::cout << boost::format("%11.6f") % my_double;

Debes #include <boost/format.hpp>


std::cout << std::fixed << std::setw( 11 ) << std::setprecision( 6 ) << my_double;

Necesitas agregar

#include <iomanip>

Necesitas manipuladores de flujo

Puede "llenar" los lugares vacíos con cualquier char que desee. Me gusta esto:

std::cout << std::fixed << std::setw( 11 ) << std::setprecision( 6 ) << std::setfill( ''0'' ) << my_double;