C++,科学记数法,格式数
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/7132957/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
C++, scientific notation, format number
提问by abcdef
Is it possible to format string in scientific notation in the following ways:
是否可以通过以下方式以科学记数法格式化字符串:
- set fixed places in exponent: 1
set fixed decimal places in mantisa: 0
double number = 123456.789
- 在指数中设置固定位置:1
在尾数中设置固定小数位:0
double number = 123456.789
So the number should be formated
所以数字应该格式化
1e+5
I am not able to set 0 decimal points for mantisa:
我无法为尾数设置 0 个小数点:
cout.precision(0);
cout << scientific << number;
result:
结果:
1.234568e+005
采纳答案by Adam Rosenfield
I'm not sure what C++ compiler you're using that's giving you 3 digits for the exponent—the C and C++ standards require a minimum of 2 digits for that, and that's what g++ does. There's no way to get only one digit using the standard C or C++ I/O functions, so you'll have to roll your own solution. Since doing a floating-point to string conversion is a very tricky problem[PDF], I'd strongly recommend not doing that and postprocessing the result instead.
我不确定您使用的是哪种 C++ 编译器,它为您提供了 3 位指数——C 和 C++ 标准要求至少 2 位数字,这就是 g++ 所做的。使用标准 C 或 C++ I/O 函数无法仅获得一位数字,因此您必须推出自己的解决方案。由于进行浮点到字符串的转换是一个非常棘手的问题[PDF],我强烈建议不要这样做,而是对结果进行后处理。
Here's one way to do that:
这是一种方法:
// 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;
}
';
}
}
回答by Praetorian
I can't figure out how to get a single digit in the exponent field but the following matches all your other requirements.
我不知道如何在指数字段中获得一个数字,但以下内容符合您的所有其他要求。
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;
}
Output:
输出:
1e+05
1e+05
EDIT:
Did a quick search through the standard (N3291) and couldn't find anything that talked about the number of digits in the exponent field when using scientific notation. This might be implementation defined.
编辑:
通过标准(N3291)进行了快速搜索,在使用科学记数法时找不到任何关于指数字段中位数的内容。这可能是实现定义的。
回答by Raven
You can actualy format anything once you have a string.. more c++ code would look like:
一旦你有了一个字符串,你就可以真正格式化任何东西……更多的 C++ 代码看起来像:
1e+5
Output:
输出:
#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;
}
You can set exponent size in expSize and this works for arbitrary large exponent.
您可以在 expSize 中设置指数大小,这适用于任意大指数。
Hope it helps!
希望能帮助到你!
回答by IceFire
Here is a stream solution:
这是一个流解决方案:
int main()
{
double e = 1.234;
cout << scientificNumber(e, 1) << " " << scientificNumber(e, 3);
return 0;
}
Usage sample:
使用示例:
#include <fmt/core.h>
double number = 123456.789;
auto s = fmt::format("{:.0e}\n", number); // s == "1e+05"
s.erase(s.size() - 2, 1); // s == "1e+5"
Output:
1.2e0 1.234e0
输出:
1.2e0 1.234e0
回答by vitaut
You can easily do this with the {fmt} formatting library:
您可以使用{fmt} 格式库轻松完成此操作:
##代码##A formatting facility based on this library is proposed for standardization in C++20: P0645.
建议使用基于此库的格式化工具以在 C++20 中进行标准化:P0645。
Disclaimer: I'm the author of {fmt}.
免责声明:我是 {fmt} 的作者。