如何“cout”一个double值的正确的小数位数?
我需要帮助保持double
精度。 如果我将一个文字赋值给double,实际值被截断。
int main() { double x = 7.40200133400; std::cout << x << "\n"; }
对于上面的代码片段,输出是7.402
有没有办法来防止这种截断? 还是有一种方法来计算double
精度浮点数? 例如, number_of_decimal(x)
会给出11,因为input在运行时是未知的,所以我不能使用setprecision()
。
我想我应该改变我的问题:如何将双精度转换为string而不截断浮点。 即
#include <iostream> #include <string> #include <sstream> template<typename T> std::string type_to_string( T data ) { std::ostringstream o; o << data; return o.str(); } int main() { double x = 7.40200; std::cout << type_to_string( x ) << "\n"; }
预期产量应为7.40200,但实际结果为7.402。 那么我该如何解决这个问题? 任何想法?
由于float
和double
在内部存储为二进制,所以文字7.40200133400
实际上代表了数字7.40200133400000037653398976544849574565887451171875
…所以你真的想要多less精度? 🙂
#include <iomanip> int main() { double x = 7.40200133400; std::cout << std::setprecision(51) << x << "\n"; }
是的,这个程序真的打印7.40200133400000037653398976544849574565887451171875!
你必须使用setiosflags(ios::fixed)
和setprecision(x)
。
例如, cout << setiosflags(ios::fixed) << setprecision(4) << myNumber << endl;
另外,不要忘记#include <iomanip.h>
。
std::cout << std::setprecision(8) << x;
请注意, setprecision
是持久的,您打印的所有下一个浮点数将以该精度打印,直到您将其更改为不同的值。 如果这是一个问题,你想解决这个问题,你可以使用代理stringstream
对象:
std::stringstream s; s << std::setprecision(8) << x; std::cout << s.str();
有关iostream格式化的更多信息,请查看cppreference中的input/输出操纵器部分。
使用Boost.Format的解决scheme:
#include <boost/format.hpp> #include <iostream> int main() { double x = 7.40200133400; std::cout << boost::format("%1$.16f") % x << "\n"; }
这输出7.4020013340000004
。
希望这可以帮助!
对此我唯一的答案是,没有办法做到这一点(如在计算小数位)正确! 主要的原因是一个数字的表示可能不是你所期望的,例如128.82,似乎是无害的,但它的实际表示是128.8199999999 …你如何计算小数位数呢?
回应你的回答 – 编辑:没有办法做到这一点。 只要给double
赋值,任何尾随的零都会丢失(对于编译器/计算机,0.402,0.4020和0.40200是相同的)。 您所指出的保留尾随零的唯一方法是将这些值存储为string(或者在跟踪您关心的数字位数并将其格式化为正确的长度的情况下进行欺骗)。
双打没有小数位。 他们有二进制的地方。 而二进制位和小数位是不可比较的(因为log2(10)
不是一个整数)。
你所要求的不存在。
让我们做一个类似的请求:在用001初始化一个整数之后,你需要用前导零来打印它。 格式化信息根本就不存储。
为了进一步理解双精度浮点存储,请看IEEE 754标准。