sirve - que es cout en c++
Impresión portátil de exponente de un iostream de doble a C++ (3)
El problema es que Visual C ++ no estaba siguiendo el estándar C99. En Visual C ++ 2015, se eliminó _set_output_format
ya que el compilador ahora sigue el estándar:
Los especificadores de formato
%e
%E
formatean un número de punto flotante como mantisa decimal y exponente. Los especificadores de formato%g
y%G
también dan formato a los números de esta forma en algunos casos. En versiones anteriores, el CRT siempre generaría cadenas con exponentes de tres dígitos. Por ejemplo,printf("%e/n", 1.0)
imprimiría1.000000e+000
. Esto era incorrecto: C requiere que si el exponente es representable usando solo uno o dos dígitos, solo se deben imprimir dos dígitos .En Visual Studio 2005, se agregó un conmutador de conformidad global:
_set_output_format
. Un programa podría llamar a esta función con el argumento_TWO_DIGIT_EXPONENT
, para permitir la impresión de exponente conforme. El comportamiento predeterminado ha cambiado al modo de impresión de exponente conforme a las normas .
Consulte Romper cambios en Visual C ++ 2015 . Para versiones anteriores, vea la respuesta de @ Manuel.
Para su información, en el estándar C99 , podemos leer:
e, E
Un doble argumento que representa un número de coma flotante se convierte en el estilo [-] d.ddd e (+ -) dd, donde hay un dígito (que es distinto de cero si el argumento es distinto de cero) antes del carácter de coma decimal y el número de dígitos después de que sea igual a la precisión; si falta la precisión, se toma como 6; si la precisión es cero y el indicador # no se especifica, no aparece ningún carácter de punto decimal. El valor se redondea a la cantidad adecuada de dígitos. El especificador de conversión E produce un número con E en lugar de e introduciendo el exponente. El exponente siempre contiene al menos dos dígitos, y solo tantos dígitos más como sea necesario para representar el exponente . Si el valor es cero, el exponente es cero. Un doble argumento que representa un infinito o NaN se convierte en el estilo de un especificador de conversión f o F.
Esta es una diferencia en comparación con C90 que no dio ninguna indicación con respecto a la longitud del exponente requerido.
Tenga en cuenta que los cambios recientes de Visual C ++ también se refieren a cómo imprimir nan
, inf
, etc.
Quiero imprimir un valor doble para std::cout
portably (GCC, clang, MSVC ++) de modo que la salida sea la misma en todas las plataformas.
Tengo un problema con el formateo del exponente. El siguiente programa
#include <iostream>
int main()
{
std::cout << 0.1e-7 << std::endl;
return 0;
}
Tiene esta salida con GCC:
1e-08
y la siguiente salida con MSVC
1e-008
¿Cómo puedo hacer que ambas salidas sean iguales?
Lo siento si esta es una pregunta tonta, pero no he encontrado una respuesta hasta el momento. Todo el formato parece evolucionar en torno al formateo de todo antes de la mantisa ...
EDITAR: La salida de GCC es 1e-08
no 1e-8
(como se dijo originalmente), por lo que es conforme. Perdón por la confusion.
EDIT2: En realidad cambió el nombre de "mantisa" por "exponente" siguiendo la observación de Dietmar. También hay una sección en Wikipedia sobre mantisa vs. significativa .
No hay ningún manipulador que controle el formateo del exponente (supongo que te refieres al exponente en lugar de a la mantisa, también, el nombre "oficial" utilizado para la mantisa es significativo ). Para empeorar las cosas, no puedo ver ninguna regla en el estándar C que restrinja el formato del exponente. Me doy cuenta de que se trata de C ++, pero a los fines de los detalles de formateo, el estándar C ++ se refiere al estándar C.
El único enfoque que conozco es utilizar una propia faceta std::num_put<char>
que formatea los valores como se desee. Esta faceta luego se pondría en una std::locale
a su vez, se imbue()
ed en std::cout
. Una implementación potencial podría usar la faceta std::num_put<char>
predeterminada (o snprintf()
que, desafortunadamente, probablemente sea más simple) para formatear el número de coma flotante y luego quitar los ceros a la izquierda del exponente.
Si bien la respuesta de Dietmar es la respuesta limpia y probablemente solo portátil, accidentalmente encontré una respuesta rápida y sucia: MSVC proporciona la función _set_output_format
que puede usar para cambiar a "imprimir exponente como dos dígitos".
La siguiente clase RAII puede crearse una instancia en su función main()
para proporcionarle el mismo comportamiento de GCC, CLANG y MSVC.
class ScientificNotationExponentOutputNormalizer
{
public:
unsigned _oldExponentFormat;
ScientificNotationExponentOutputNormalizer() : _oldExponentFormat(0)
{
#ifdef _MSC_VER
// Set scientific format to print two places.
unsigned _oldExponentFormat = _set_output_format(_TWO_DIGIT_EXPONENT);
#endif
}
~ScientificNotationExponentOutputNormalizer()
{
#ifdef _MSC_VER
// Enable old exponent format.
_set_output_format(_oldExponentFormat);
#endif
}
};