简洁准确的双打印刷

时间:2016-01-25 17:31:32

标签: c++ printf

我有double x我希望以字符串s打印。我希望表示符合以下属性:

  • 准确(x - atof(s))的绝对值小于epsilon
  • 简明:该表示不包含比准确要求更高的有效数字

这样做的最佳方式是什么?

说明为什么%f%g不能完成这项工作:

printf("%f\n", 1.0);              // 1.000000       not concise
printf("%g\n", 1.0);              // 1              good
printf("%f\n", 4357890.2342389);  // 4357890.234239 good
printf("%g\n", 4357890.2342389);  // 4.35789e+06    not accurate

3 个答案:

答案 0 :(得分:4)

您可以使用(cpplearner提及的)格式说明符%.16g作为printf,或者使用std::coutstd::setprecision执行此操作:

#include <iostream>
#include <iomanip>

int main()
{
    std::cout << 4357890.2342389 << std::endl;

    std::cout << std::setprecision(16);

    std::cout << 4357890.2342389 << std::endl;
    std::cout << 1.0 << std::endl;

    std::cout << std::fixed;
    std::cout << "fixed\n";

    std::cout << 4357890.2342389 << std::endl;
}

产生:

4.35789e+06
4357890.2342389
1
fixed
4357890.2342389002442360

在线代码link

注意:您必须始终考虑浮点精度问题。

推荐阅读:What Every Computer Scientist Should Know About Floating-Point Arithmetic

答案 1 :(得分:1)

为了满足您的要求,您可以做一些丑陋的事情:

#include <iostream>
#include <iomanip>
#include <sstream>
#include <string>

std::string concise_and_accurate( double x, int prec ) {
    // print the number to a stringstream with all the figures needed
    std::stringstream strnum;
    strnum << std::fixed << std::setprecision(prec) << x;
    std::string str = strnum.str();
    // cancel the extra zeroes at the right
    str.erase( str.find_last_not_of('0') + 1, std::string::npos );
    // delete the '.' if there are no other digits at the right
    if ( str[str.size()-1] == '.' ) str.erase(str.size()-1);
    return str; 
}


int main() {
    double test[] = { 4357890.2342389, 1.0, 1.0/3, 100.0/3 };

    for ( auto x : test ) {
        std::cout << concise_and_accurate(x,6) << '\n';
    }

    return 0;
}

输出结果为:

4357890.234239
1
0.333333
33.333333

答案 2 :(得分:0)

您可以配置格式说明符,如下所述:

Format specifiers in C

由于您将此标记为C ++,为什么不试试这个:

#include <iostream>

std::cout << double(1.0) << std::endl
std::cout << 1.0 << std::endl
std::cout << double(4357890.2342389) << std::endl    
std::cout << 4357890.2342389 << std::endl

如果你想要更高的精度,你可以

std::cout << std::setw(32) << std::setprecision(16) << double(1.0);

为什么会打印出更多数字字符。