C++ Setprecision 令人困惑
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/5623689/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Setprecision is Confusing
提问by Marc Quebrar Tan
I just want to ask about setprecision because I'm a bit confused.
我只是想问一下 setprecision 因为我有点困惑。
here's the code:
这是代码:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
double rate = x;
cout << fixed << setprecision(2) << rate;
}
where x = to following:
其中 x = 以下:
the left side of equation are the values of x.
等式左边是 x 的值。
1.105 = 1.10 should be 1.11
1.105 = 1.10 应该是 1.11
1.115 = 1.11 should be 1.12
1.115 = 1.11 应该是 1.12
1.125 = 1.12 should be 1.13
1.125 = 1.12 应该是 1.13
1.135 = 1.14 which is correct
1.135 = 1.14 这是正确的
1.145 = 1.15 also correct
1.145 = 1.15 也正确
but if x is:
但如果 x 是:
2.115 = 2.12 which is correct
2.115 = 2.12 这是正确的
2.125 = 2.12 should be 2.13
2.125 = 2.12 应该是 2.13
so why in a certain value it's correct but sometimes it's wrong?
那么为什么在某个值下它是正确的,但有时却是错误的呢?
please enlighten me. thanks
请赐教。谢谢
回答by NPE
There is no reason to expect that any of the constants in your post can be represented exactlyusing the floating-point system. As a consequence, the exact halves that you have may no longer be exact halves once you store them in a double
variable (regardless of how the iostreams are meant to round such numbers.)
没有理由期望您文章中的任何常量都可以使用浮点系统精确表示。因此,一旦您将它们存储在double
变量中,您拥有的确切一半可能不再是确切的一半(无论 iostream 是如何舍入这些数字的。)
The following code illustrates my point:
以下代码说明了我的观点:
#include <iostream>
#include <iomanip>
using namespace std;
int main()
{
double rate = 1.115;
cout << fixed << setprecision(20) << rate;
}
Output:
输出:
1.11499999999999999112
I would recommend taking a look at the FAQ.
我建议您查看常见问题解答。
回答by Mark B
Some of the numbers you're printing may not be representable as a floating point number and may actually be lower or higher than you think, directly affecting the rounding.
您打印的某些数字可能无法表示为浮点数,并且实际上可能低于或高于您的想象,直接影响舍入。
Since you're trying to format a floating point number to fixed point, have you considered actually USING a fixed point number (int/long scaled by say 1000 depending on your needs) that has its own insert operator defined? Then you'll always get accurate display and rounding without needing to rely on setprecision
having any particular behavior (I couldn't find the relevant conversion section in the standard in a quick look).
由于您试图将浮点数格式化为定点数,您是否考虑过实际使用定义了自己的插入运算符的定点数(int/long,根据您的需要按 1000 缩放)?然后,您将始终获得准确的显示和舍入,而无需依赖于setprecision
任何特定行为(我无法快速查看标准中的相关转换部分)。
回答by James Kanze
Why do you say that 1.105 should be 1.11? The C++ standard says nothing about it, but the default rounding mode on most of the usual machines (Intel, Sparc, etc.) is round to even, so 1.105 should be 1.10. In general, when the exact result is exactly between two representable values, the rule is to round to the one with an even least significant digit.
为什么说1.105应该是1.11呢?C++ 标准对此没有说明,但是大多数常用机器(Intel、Sparc 等)上的默认舍入模式是舍入到偶数,因此 1.105 应该是 1.10。通常,当精确结果正好在两个可表示值之间时,规则是四舍五入到具有偶数最低有效位的那个。
I also wonder where you're getting these values. On the usual machines, 1.105 can't be represented, so you have something slightly larger or slightly smaller.
我也想知道你从哪里得到这些值。在通常的机器上,1.105 无法表示,所以你有一些稍大或稍小的东西。
And of course, the above comments apply for all of the other values you've cited.
当然,上述评论适用于您引用的所有其他值。