具有固定宽度的双到字符串转换

时间:2014-05-31 14:18:55

标签: c++ formatting

我想将double值打印成不超过8个字符的字符串。打印的数字应尽可能多,例如

5.259675
48920568
8.514e-6
-9.4e-12

我尝试了C ++ iostreams和printf - 样式,并且都没有按照我希望的方式尊重提供的大小:

cout << setw(8) <<  1.0 / 17777.0 << endl;
printf( "%8g\n", 1.0 / 17777.0 );

给出:

5.62525e-005
5.62525e-005

我知道我可以指定一个精度,但我必须在这里提供一个非常小的精度,以便覆盖最坏的情况。任何想法如何在不牺牲太多精度的情况下强制确切的场宽?我需要这个用于打印矩阵。我真的需要提出自己的转换功能吗?

5年前有人问过类似的问题:Convert double to String with fixed width,没有令人满意的答案。我当然希望在此期间取得一些进展。

2 个答案:

答案 0 :(得分:1)

实际上,这似乎并不太难,尽管你不能在一个函数调用中做到这一点。指数使用的字符位数非常容易预测:

const char* format;
if (value > 0) {
    if (value < 10e-100) format = "%.1e";
    else if (value < 10e-10) format = "%.2e";
    else if (value < 1e-5) format = "%.3e";
}

等等。

只有,定义了printf行为的C标准坚持指数的至少两位数,所以它浪费了一些。见c++ how to get "one digit exponent" with printf

合并这些修补程序会使代码变得相当复杂,尽管仍然不如自己进行转换那么糟糕。

答案 1 :(得分:0)

如果您想转换为固定的十进制数字(例如,删除+ / - &#34; E&#34;部分),那么它将更容易实现:

#include <stdio.h>
#include <cstring>     // strcpy
#include <iostream>     // std::cout, std::fixed
#include <iomanip>      // std::setprecision
#include <new>

char *ToDecimal(double val, int maxChars) 
{
    std::ostringstream buffer;
    buffer << std::fixed << std::setprecision(maxChars-2) << val;
    std::string result = buffer.str();

    size_t i = result.find_last_not_of('\0');
    if (i > maxChars) i = maxChars;
    if (result[i] != '.') ++i;
    result.erase(i);

    char *doubleStr = new char[result.length() + 1];
    strcpy(doubleStr, (const char*)result.c_str());

    return doubleStr;
}

int main()
{
    std::cout << ToDecimal(1.26743237e+015, 8) << std::endl;
    std::cout << ToDecimal(-1.0, 8) << std::endl;
    std::cout << ToDecimal(3.40282347e+38, 8) << std::endl;
    std::cout << ToDecimal(1.17549435e-38, 8) << std::endl;
    std::cout << ToDecimal(-1E4, 8) << std::endl;
    std::cout << ToDecimal(12.78e-2, 8) << std::endl;
}

输出:

12674323
-1
34028234
0.000000
-10000
0.127800