我有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
答案 0 :(得分:4)
您可以使用(cpplearner提及的)格式说明符%.16g
作为printf,或者使用std::cout
和std::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)
您可以配置格式说明符,如下所述:
由于您将此标记为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);
为什么会打印出更多数字字符。