简体   繁体   English

为什么std :: cout将4.9999999打印为5?

[英]Why does std::cout print 4.9999999 as 5?

I was figuring out the difference between log(3) and log10(3) , using this code: 我正在使用以下代码找出log(3)log10(3)之间的区别:

void testPrecisionError() {
    cout
    << log(243) / log(3) << " : "
    << int(log(243) / log(3)) << " : "
    << endl;

    cout
    << log10(243) / log10(3) << " : "
    << int(log10(243) / log10(3)) << " : ")
    << endl;
}

The output is: 输出为:

5 : 4  // I think it is 4.999999 underlying
5 : 5

I found out that 4.999999 is printed out as 5 . 我发现4.999999被打印为5

Why doesn't C++ print it as 4.99999 like Java does? 为什么C ++不像Java那样将其打印为4.99999

I guess I could no more cout to convince myself that there is NO PRECISON LOSS ! 我想我可以不再cout说服自己,没有精密度的损失!

Because it's rounding to the nearest value of the last digit of the requested precision. 因为它四舍五入到所请求精度的最后一位数字的最近值。 The actual value is about: 实际值约为:

4.99999999999999911182158029987

And with 6 digits of precision, that's closer to 5.000000 than 4.999999 , so it shows 5 . 精度为6位数字,比4.999999接近5.000000 ,因此显示5 If you use setprecision(16) or higher you'll see all the 9's. 如果使用setprecision(16)或更高版本,则会看到所有9。

When you cast to int , it always truncates, it doesn't round to the nearest value. 当您强制转换为int ,它总是会被截断,不会舍入到最接近的值。

As for why Java displays it as 4.999999 , maybe it just discards extra digits rather than rounding. 至于为什么Java将其显示为4.999999 ,也许它只是丢弃多余的数字而不是舍入。

Welcome to the world of binary where real numbers cannot be represented correctly! 欢迎来到不能正确表示实数的二进制世界! double and float have a precision problem. doublefloat具有精度问题。 So you need to be careful when you are comparing 2 double values etc... 因此,在比较2个double值等时,您需要格外小心。

For example: 例如:

  • sqrt(2) = [real value of sqrt(2)] +/- [precision error]
  • precision error depend on the type / cpu architecture you are using (double, float...) 精度误差取决于您使用的类型/ cpu体系结构(double,float ...)

Floating point output in iostreams is controlled by the stream's precision . iostream中的浮点输出受流的精度控制 The default IIRC is 6 places to the right of the decimal. 默认的IIRC是小数点右边的6位。 If the 7th digit is a 9, it rounds the 6th digit up, and so on. 如果第7位数字为9,则将第6位数字四舍五入,依此类推。 In your case, 4.9999999... becomes 5. 您的情况是4.9999999 ...变成5。

Maximum decimal precision in IEEE 754, which is probably what you're using, is around 15 decimal places. IEEE 754中可能使用的最大十进制精度约为15个小数位。 If you set the stream's precision to 16 or so (with the setprecision manipulator), you'll see "all" the digits. 如果将流的精度设置为16左右(使用setprecision机械手),则将看到“所有”数字。 But of course it's still only an approximation, because that what floating-point numbers are. 但是,当然,这仍然只是一个近似值,因为那是什么浮点数。

Why isn't it like Java? 为什么它不像Java? Two languages, two sets of rules. 两种语言,两组规则。 I'd argue that Java is wrong: if the 7th position is 9, then 4.99999 is off by 0.0000009+, whereas 5.0 is off by only 0.0000001+. 我认为Java是错误的:如果第7位为9,则4.99999被0.0000009+所抵消,而5.0仅被0.0000001+所抵消。 Do you want more digits, or a closer approximation? 您想要更多的数字还是更近似的数字?

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM