【问题标题】:Convert double to String with fixed width将双精度转换为固定宽度的字符串
【发布时间】:2010-12-02 13:00:14
【问题描述】:

我想将双精度转换为固定宽度的字符串。

如果宽度是 10,那么我希望双精度值四舍五入到这个宽度。

例如,如果 value = 102.121323435345 并且宽度是 10,那么这个值应该是,

位置==> 0123456789 值 = 102.121323

我可以用 snprintf 实现这一点,但我正在寻找一个 c++ 本地代码来做同样的事情。


char buf[125];
snprint(buf, width, "%.6f", value);

我尝试使用以下内容,但对我没有多大帮助,

 
std::ostringstream oss;
oss &lt&lt std::fixed &lt&lt std::setw(10) &lt&lt std::precision(6) &lt&lt value;

std::setw 保证该值的最小宽度,如果该值大于宽度大小,它不会对值进行四舍五入。

谢谢。

【问题讨论】:

  • 我不太清楚的事情:您是否尝试像示例输出中那样以 10 的宽度打印,或者像在您的 c 代码中那样使用 4 位小数?
  • 为什么反对使用 snprintf?这是完全有效的 C++。 ostringstream 对此太过分了。
  • @Martin,我希望宽度始终保持不变

标签: c++ string-formatting


【解决方案1】:

这就是你想要的吗?在这里,我们计算可用精度的数量并相应地设置 ostream。

    #include <iostream>
    #include <iomanip>

    using namespace std;

    int main(int argc, char* argv[])
    {
    // Input
    double value =  102.1213239999;
    // Calculate limits
    int digits = ( (value<1) ? 1 : int(1+log10(double(abs(value)))) );
    int width = 10;
    int precision = (((width-digits-1)>=0) ? (width-digits-1):0);

    // Display
    cout.setf(ios::fixed);
    cout.precision(precision);
    cout<<setw(10)<<value<<endl;


    return 0;

    }
    OUTPUT: 102.121324

顺便说一句,如果您想要大量计算数字的方法,here's how.

【讨论】:

  • OP 希望以最大精度输出 10 个字符。
  • 当值 > 1e9 时会发生什么?
  • 现在怎么样?如果大于 1e9,它不会停留在 10 个字符,但精度问题已解决(我认为)。
【解决方案2】:

词法转换怎么样?

double x = 102.1213239999;
std::cout << boost::lexical_cast<std::string>(x).substr(0,10);

这不完全符合您的要求。我只是想跳出框框思考。
您可能还想查看这个问题以讨论格式化 differences between C and C++ 并查看 Boost Format Library

【讨论】:

  • 这是错误的。考虑这个数字:double x = 12345678901。您的答案将相差几个数量级。
  • 即使示例错误,查看 Boost Format 库的建议也值得 +1。
  • @unknown:我发现绝对陈述通常是错误的(这可能不是一个好的解决方案)。我知道大值会被截断,但问题是关于将数据拟合到固定大小的输出字段而不是准确性(否则使用操纵器 width(10) 的解决方案是微不足道的)。在原始问题 snprint() 用于截断输出中,此替代方案在 C++ 中提供了等效(但更简洁)的解决方案。真正的问题是当你有一个固定大小的输出字段并且值更大时你会怎么做!这就是为什么 width(x) 指定最小宽度而不是最大宽度的原因。
【解决方案3】:

您可以使用osteram::widthostream::precision 函数来实现您的目标,就像这样

std::ostringstream out;
out.width(10);
out.precision(10);
out << 123.12345678910111213;

虽然它不会在点后添加零以尊重宽度,但它会在数字前添加空格(或您选择的任何字符)。因此,如果您将 102 作为输入值传递,您将得到 '102' 或 '0000000102'(如果您调用 out.fill('0');)而不是 '102.000000'。

【讨论】:

    【解决方案4】:
    int main() {
        double x=3.543732;
        cout << to_string(x).substr(0,5);
        return 0;
    }
    

    【讨论】:

      猜你喜欢
      • 2014-07-21
      • 2011-08-11
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多