2016-07-16 106 views
1

我被搞清楚log(3)log10(3)之间的差异,使用此代码:为什么std :: cout打印4.9999999为5?

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

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

的输出是:

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

我发现4.999999被打印出来5

为什么C++不像Java那样将其打印为4.99999

我想我不能再更多cout来说服自己,没有任何的PRECISON LOSS!

+5

默认精度为6. –

+0

为什么C++不像Java那样打印4.99999? –

+0

4.99999只有5位数的精度,而不是6,如默认值C –

回答

0

欢迎来到二元世界,其中实数不能正确表示! doublefloat有一个精确的问题。所以,你必须要小心,当你比较2个double值等等

例如:

  • sqrt(2) = [real value of sqrt(2)] +/- [precision error]
  • 精度误差取决于你使用(双,浮点型/ CPU架构...)
+0

为什么C++不打印它为4.99999如Java? –

+0

Java可能有其他类型的float/double值表示,其精度优于C(使用类等)。 – Phong

+0

Java use IEEE 754 –

3

因为它四舍五入到要求的精度的最后一位数字的最接近的值。实际值约为:

4.99999999999999911182158029987 

而且随着精度6位,这是更接近5.0000004.999999,因此它显示5。如果你使用setprecision(16)或更高,你会看到所有的9。

当您投射到int时,它总是截断,它不会四舍五入到最接近的值。至于为什么Java将它显示为4.999999,或许它只是放弃了额外的数字而不是四舍五入。

+0

Java不显示为4.999999,它显示为4.999999999999999。 –

0

iostream中的浮点输出由流的precision控制。默认的IIRC在小数点右边6位。如果第7位数字是9,则将第6位数字向上舍入,依此类推。在您的情况下,4.9999999 ...变为5.

IEEE 754中的最大小数精度(可能是您使用的值)大约是小数点后15位。如果您将流的精度设置为16或更高(使用setprecision操纵器),您将看到“全部”数字。但它当然只是一个近似值,因为它是什么浮点数。

为什么它不像Java?两种语言,两套规则。我认为Java是错误的:如果第7个位置是9,那么4.99999被关闭0.0000009+,而5.0关闭只有0.0000001+。你想要更多的数字还是更接近的近似值?