C++, научная нотация, номер формата
можно ли форматировать строку в научной нотации следующими способами:
- установить фиксированные места в экспоненте: 1
-
установить фиксированные десятичные знаки в mantisa: 0
double number = 123456.789
таким образом, число должно быть сформировано
1e+5
Я не могу установить 0 десятичных знаков для mantisa:
cout.precision(0);
cout << scientific << number;
результат:
1.234568e+005
4 ответов
Я не уверен, какой компилятор C++ вы используете, который дает вам 3 цифры для экспоненты-стандарты C и c++ требуют минимум 2 цифр для этого, и это то, что делает g++. Невозможно получить только одну цифру, используя стандартные функции ввода-вывода C или C++, поэтому вам придется свернуть собственное решение. Поскольку преобразование с плавающей запятой в строку является очень сложная проблема [PDF], я настоятельно рекомендую не делать этого и постобработать результат вместо.
вот один из способов сделать это:
// C version; you can rewrite this to use std::string in C++ if you want
void my_print_scientific(char *dest, size_t size, double value)
{
// First print out using scientific notation with 0 mantissa digits
snprintf(dest, size, "%.0e", value);
// Find the exponent and skip the "e" and the sign
char *exponent = strchr(dest, 'e') + 2;
// If we have an exponent starting with 0, drop it
if(exponent != NULL && exponent[0] == '0')
{
exponent[0] = exponent[1];
exponent[1] = '';
}
}
Я не могу понять, как получить одну цифру в поле экспоненты, но следующее соответствует всем вашим другим требованиям.
#include <iostream>
#include <iomanip>
int main()
{
const double number = 123456.789;
std::cout << std::setprecision(0) << std::scientific << number << std::endl;
}
выход:
1e+05
EDIT:
Сделал быстрый поиск по стандарту (N3291) и не смог найти ничего, что говорило бы о количестве цифр в поле экспоненты при использовании научной нотации. Это может быть определено реализацией.
вы можете фактически форматировать все, что у вас есть строка.. больше кода c++ будет выглядеть так:
const double number = 123456.789;
const int expSize = 1;
std::ostringstream oss;
std::string output;
oss << std::scientific << number;
unsigned int ePos = oss.str().find("e");
unsigned int dPos = oss.str().find(".");
if(ePos == 0){
//no exponent
}
else if(dPos == 0){
//not decimal
}
else{
output = oss.str().substr(0, dPos) + oss.str().substr(ePos, 2);
if(oss.str().size()-expSize > ePos+1)
output += oss.str().substr(oss.str().size()-expSize, oss.str().size());
else{
//expSize too big (or bug -> e used but no exponent?)
}
std::cout << output;
}
выход:
1e+5
вы можете установить размер экспоненты в expSize, и это работает для произвольного большого показателя.
надеюсь, что это помогает!
вот потоковое решение:
#include <iostream>
#include <iomanip>
using namespace std;
template<typename T>
struct scientificNumberType
{
explicit scientificNumberType(T number, int decimalPlaces) : number(number), decimalPlaces(decimalPlaces) {}
T number;
int decimalPlaces;
};
template<typename T>
scientificNumberType<T> scientificNumber(T t, int decimalPlaces)
{
return scientificNumberType<T>(t, decimalPlaces);
}
template<typename T>
std::ostream& operator<<(std::ostream& os, const scientificNumberType<T>& n)
{
double numberDouble = n.number;
int eToThe = 0;
for(; numberDouble > 9; ++eToThe)
{
numberDouble /= 10;
}
// memorize old state
std::ios oldState(nullptr);
oldState.copyfmt(os);
os << std::fixed << std::setprecision(n.decimalPlaces) << numberDouble << "e" << eToThe;
// restore state
os.copyfmt(oldState);
return os;
}
пример использования:
int main()
{
double e = 1.234;
cout << scientificNumber(e, 1) << " " << scientificNumber(e, 3);
return 0;
}
выход:
1.2e0 1.234e0