Long double 不会打印为我初始化它的常量
可能的重复:
浮点不准确示例
我遇到问题...当我编译 src 时,变量显示与我初始化的不一样,请参阅:
#include <iostream>
using namespace std;
int main()
{
long double mynum = 4.7;
cout.setf(ios::fixed,ios::floatfield);
cout.precision( 20 );
cout << mynum << endl;
}
然后:
[fpointbin@fedora ~]$ ./a.out
4.70000000000000017764
如何修复它?我想“cout”显示 4.700000...
Possible Duplicate:
Floating point inaccuracy examples
Im having a problem... When i compile the src, the variable showed isn't the same that i initialized, see it:
#include <iostream>
using namespace std;
int main()
{
long double mynum = 4.7;
cout.setf(ios::fixed,ios::floatfield);
cout.precision( 20 );
cout << mynum << endl;
}
And then:
[fpointbin@fedora ~]$ ./a.out
4.70000000000000017764
How to fix it? I want to "cout" shows 4.700000...
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(5)
您的变量是
long double
,但文字4.7
的默认精度仅为double
。由于您将其打印为long double
,因此解释会选择使用足够的有效数字来打印它,以将其与相邻的long double
值区分开来,即使这些相邻值不是可能的double
。Your variable is
long double
, but the default precision of the literal4.7
is onlydouble
. Since you're printing it aslong double
, the interpretation chooses to print it with enough significant digits to distinguish it from neighbouringlong double
values, even though those neighbouring values are not possibledouble
s.双精度数的内部表示不允许 4.7 的“精确”表示。 “最接近”是 4.70000000000000017764。实际上,当您有 64 位双精度数时,无需考虑 20 的精度。最大有效精度约为 15。尝试使用 12 左右,
您应该会得到您想要看到的结果。
The internal representation of doubles does not allow for an 'exact' representation of 4.7. The 'closest' is 4.70000000000000017764. In reality there is no need to look at a precision of 20 when you have 64 bit doubles. The maximum effective precision is about 15. Try using 12 or so,
and you should get what you want to see.
大多数平台,包括您的平台,只能准确地表示那些具有短的、有限的二进制展开式的浮点数,即,它们是 2 的幂的有限和。 4.7不是这样的数字,因此它无法在您的平台上精确表示,如果您要求过高的精度(20太多了,因为您的尾数有64位,而log_10(64)是19.27),那么您将不可避免地面临小错误。
(但是,正如 @Henning 所说,从(非长)双精度值分配时,您已经失去了精度;您应该将文字常量写为长双精度值:
4.7L
。然后您应该只看到第 20 位数字有误。)Most platforms, including yours, can only represent those floating point numbers exactly which have a short, finite binary expansion, i.e. which are finite sums of powers of two. 4.7 is not such a number, so it cannot be represented precisely on your platform, and if you demand excessive precision (20 is too much as your mantissa has 64 bits, and log_10(64) is 19.27), then you will inevitably face small errors.
(However, as @Henning says, you are already losing precision when assigning from a (non-long) double; you should write your literal constant as a long double:
4.7L
. Then you should only see an error in the 20th digit.)float
和double
是二进制浮点类型,即它们以 2 为基数存储尾数和指数。这意味着任何不能精确表示为的十进制数尾数的有限位数将被近似;您展示的问题来自于此: 4.7 无法精确表示为
double
的尾数(文字4.7
的类型为double
,值得称赞@Henning Makholm 发现它),所以使用最接近的近似值。为了更好地可视化问题:在基数 3 中,2/3 是一个具有有限表示的数字(即 0.23),而在基数 10 中,它是一个周期数(0,6666666...) ;如果数字空间有限,则必须执行近似,即 0,66666667。这里的情况完全相同,源基数为 10,“目标”基数为 2。
如果有特殊需要避免这种近似值(例如,在处理十进制金额时),请使用特殊的
decimal 类型,以 10 为基数存储尾数和指数(C++ 不提供自己的此类类型,但网络上有许多
decimal
类可用);尽管如此,对于“正常”/科学计算,仍使用二进制 FP 类型,因为它们更快且更节省空间。float
s anddouble
s are binary floating-point types, i.e. they store a mantissa and an exponent in base 2.This means that any decimal number that cannot be represented exactly into the finite digits of the mantissa will be approximated; the problem you showed comes from this: 4.7 cannot be represented exactly into the mantissa of a
double
(the literal4.7
is of typedouble
, kudos @Henning Makholm for spotting it), so the nearest approximation is used.To better visualize the problem: in base 3, 2/3 is a number with a finite representation (i.e. 0.23), while in base 10 it is a periodic number (0,6666666...); if you have only a finite space for digits, you'll have to perform an approximation, that will be 0,66666667. That's exactly the same thing here, with the source base being 10 and the "target" base being 2.
If there's a special need to avoid this kind of approximations (e.g. when dealing with decimal amounts of money) special
decimal
types can be used, that store mantissa and exponent in base 10 (C++ do not provide such type of its own, but there are manydecimal
classes available on the Net); still, for "normal"/scientific calculations binary FP types are used, because they are much faster and more space-efficient.某些数字不能用基数 2 表示。显然,4.7 就是其中之一。您看到的是最接近 4.7 的可表示数字。
除了将精度设置为较低的数字之外,您对此无能为力。
Certain numbers cannot be represented in base two. Apparently, 4.7 is one of them. What you're seeing is the closest representable number to 4.7.
There's nothing you can do about this, other than setting the precision to a lower number.