打印Python和C ++时的精度差异加倍

时间:2015-09-03 23:05:42

标签: python c++ floating-point double

我目前对此感到惊讶:

C ++ 11

#include <iostream>
#include <iomanip>
#include <limits>

int main()
{
  double d = 1.305195828773568;
  std::cout << std::setprecision(std::numeric_limits<double>::max_digits10) << d << std::endl;
  // Prints  1.3051958287735681
}

的Python

>>> repr(1.305195828773568)
'1.305195828773568'

发生了什么,为什么C ++中的额外1?

到目前为止,我认为C ++和Python使用相同的64位IEEE双打;两种格式化函数都应该打印出完整的精度。

3 个答案:

答案 0 :(得分:10)

你可以强制python打印1(以及更多以下数字):

print('{:.16f}'.format(1.305195828773568))
# -> 1.3051958287735681

来自https://docs.python.org/2/tutorial/floatingpoint.html

>>> 7205759403792794 * 10**30 // 2**56
100000000000000005551115123125L
     

在Python 2.7和Python 3.1之前的版本中,Python对此进行了四舍五入   值为17位有效数字,给出'0.10000000000000001'。在   当前版本,Python显示基于最短的值   正确舍入回到真实二进制值的小数部分,   结果只是'0.1'。

&#34;打印全精度&#34;很难做到:全精度是多少?浮点数的表示是二元的;只能得到2的幂的分数(完全精确);大多数小数部分不能在基数2中精确表示。

但是内存中的float对于python和c ++是相同的;它只是字符串表示不同。

答案 1 :(得分:3)

当格​​式以固定点表示法结束时,precision()指定小数位数。由于您的示例中还有一个非小数位数,因此创建了一个非安全表示的数字。

使用科学记数法时,会计算总位数,并且您将获得与原始位数相同的位数(当然还有一个指数)。用于格式化浮点数的C和C ++选项实际上相当糟糕。特别是,没有选项可以让格式化程序决定适当的位数,尽管基础算法实际上可以确定这些位数。

答案 2 :(得分:2)

取自this question的回答:

  

IEEE 754浮点以二进制形式完成。从给定的位数到给定的小数位数没有精确的转换。 3位可以保存0到7之间的值,4位可以保存0到15之间的值.0到9之间的值大约需要3.5位,但这也不准确。

     

IEEE 754双精度数占64位。其中,52位专用于有效数字(其余为符号位和指数)。由于有效数是(通常)归一化的,因此有一个隐含的第53位。

     

现在,给定53位和每位大约3.5位,简单除法给出了15.1429位精度。但请记住,每个十进制数字3.5位只是一个近似值,而不是一个完全准确的答案。

你提供的15位数之后的这个奇怪的.1429可能是添加的1位数的罪魁祸首。

对于它的价值,Python在他们的网站上写了这个:

  

历史上,Python提示符和内置repr()函数将选择具有17位有效数字的那一个,即0.10000000000000001。从Python 3.1开始,Python(在大多数系统上)现在能够选择最短的这些并且只显示0.1。