C++,科学计数法,格式编号

发布于 2024-11-30 17:12:31 字数 355 浏览 1 评论 0原文

是否可以通过以下方式以科学记数法格式化字符串:

  • 在指数中设置固定位置:1

  • 在尾数中设置固定小数位:0

     双数 = 123456.789
    

因此,应该格式化数字

  1e+5

我无法为尾数设置 0 小数点:

cout.precision(0);
cout << scientific << number;

结果:

1.234568e+005

Is it possible to format string in scientific notation in the following ways:

  • set fixed places in exponent: 1

  • set fixed decimal places in mantissa: 0

     double number = 123456.789
    

So the number should be formated

  1e+5

I am not able to set 0 decimal points for mantissa:

cout.precision(0);
cout << scientific << number;

result:

1.234568e+005

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

优雅的叶子 2024-12-07 17:12:31

您可以使用 C++20 std::format

double number = 123456.789;
auto s = std::format("{:.0e}\n", number); // s == "1e+05"
s.erase(s.size() - 2, 1); // s == "1e+5"

std::format 广泛使用之前,您可以使用 {fmt}库std::format 基于:

#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"

免责声明:我是 {fmt} 和 C++20 std:: 的作者格式

You can do it with C++20 std::format:

double number = 123456.789;
auto s = std::format("{:.0e}\n", number); // s == "1e+05"
s.erase(s.size() - 2, 1); // s == "1e+5"

Until std::format is widely available you can use the {fmt} library, std::format is based on:

#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"

Disclaimer: I'm the author of {fmt} and C++20 std::format.

逆流 2024-12-07 17:12:31

我不知道如何在指数字段中获取单个数字,但以下内容符合您的所有其他要求。

#include <iostream>
#include <iomanip>

int main()
{
  const double number = 123456.789;

  std::cout << std::setprecision(0) << std::scientific << number << std::endl;
}

输出:

1e+05

编辑:
快速搜索了标准(N3291),但找不到任何关于使用科学记数法时指数字段中的位数的内容。这可能是实现定义的。

I can't figure out how to get a single digit in the exponent field but the following matches all your other requirements.

#include <iostream>
#include <iomanip>

int main()
{
  const double number = 123456.789;

  std::cout << std::setprecision(0) << std::scientific << number << std::endl;
}

Output:

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.

空‖城人不在 2024-12-07 17:12:31

我不确定您使用的 C++ 编译器会为您提供 3 位指数 - C 和 C++ 标准要求至少 2 位数字,而这正是 g++ 所做的。使用标准 C 或 C++ I/O 函数无法仅获取一位数字,因此您必须推出自己的解决方案。由于进行浮点到字符串转换是一个非常棘手的问题 [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] = '\0';
    }
}

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.

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] = '\0';
    }
}
手长情犹 2024-12-07 17:12:31

一旦你有了一个字符串,你实际上可以格式化任何东西。更多的 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 中设置指数大小,这适用于任意大指数。

希望有帮助!

You can actualy format anything once you have a string.. more c++ code would look like:

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+5

You can set exponent size in expSize and this works for arbitrary large exponent.

Hope it helps!

只想待在家 2024-12-07 17:12:31

这是一个流解决方案:

#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

Here is a stream solution:

#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;
}

Usage sample:

int main()
{
    double e = 1.234;

    cout << scientificNumber(e, 1) << " " << scientificNumber(e, 3);

    return 0;
}

Output:
1.2e0 1.234e0

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文