【问题标题】:Unable to see Python's approximations in mathematical calculations在数学计算中看不到 Python 的近似值
【发布时间】:2010-11-05 16:57:57
【问题描述】:

问题:在我使用 Python 时查看计算机何时在数学计算中进行近似

问题示例:

我的老老师曾经说过这样一句话

You cannot never calculate 200! with your computer. 

我现在不完全确定这是否属实。 似乎是这样,因为我从 Python script 那里得到了很多零。

如何查看 Python 代码何时进行近似计算?

【问题讨论】:

  • 计算 200 并不难!这些日子。见www53.wolframalpha.com/input/?i=200!
  • 请注意,上面的 URL 应该包含“!”特点。我不确定为什么 SO 不将其作为链接的一部分。
  • 自动链接文本以忽略 URL 末尾的标点符号(正斜杠除外)通常是一种很好的做法。 99% 的情况下,用户在括号或句子中包含了非标点 URL,包含标点符号会破坏链接。你只是不幸成为剩下的 1% 的案例之一。

标签: python


【解决方案1】:

Python 使用arbitrary-precision arithmetic 来计算整数,所以它可以精确计算200!。对于实数(所谓的floating-point),Python 不使用精确表示。它使用称为IEEE 754 的二进制表示法,它本质上是科学记数法,但以2 为底而不是10 为底。

因此,任何无法以 53 位精度以 2 为底数精确表示的实数,Python 无法产生精确结果。例如,0.1(以 10 为底)是以 2 为底的无限小数,0.0001100110011...,因此无法精确表示。因此,如果您在 Python 提示符下输入:

>>> 0.1
0.10000000000000001

返回的结果不同,因为已从十进制转换为二进制(精度为 53 位),再转换为十进制。结果,你会得到这样的结果:

>>> 0.1 + 0.2 == 0.3
False

如需良好(但较长)的阅读,请参阅What Every Programmer Should Know About Floating-Point Arithmetic

【讨论】:

    【解决方案2】:

    Python 以 long 类型的形式具有无限的 integer 大小。也就是说,如果是整数,则对数字大小的限制受Python可用内存的限制。

    当您计算一个大数(例如 200)时!你会在它的末尾看到一个 L,这意味着 Python 已经自动将 int 转换为 long,因为 int 不够大,无法容纳该数字。

    有关详细信息,请参阅this page 的第 6.4 节。

    【讨论】:

    • AND...这不需要“近似值”。
    • 顺便说一下,在 Python 3.0 中,“常规”整数和“长”整数之间没有区别。系统在它们之间无缝转换,因此不再有 L。
    【解决方案3】:

    200!确实是一个很大的数字。

    如果 IEEE 64 位双精度的范围是 1.7E +/- 308(15 位),您可以看到可以得到的最大阶乘约为 170!。

    Python 可以处理任意大小的数字,Java 也可以处理 BigInteger。

    【讨论】:

      【解决方案4】:

      如果没有对该声明进行某种澄清,这显然是错误的。仅从个人经验来看,早期的编程课程(在 1980 年代后期)包括解决非常相似(如果不完全相同)的问题。一般来说,要知道某些进行计算的设备没有进行近似,您必须证明(在证明的数学意义上)它不是。

      Python 的整数类型(在 2.x 中命名为 intlong,在 3.x 中都折叠成 int 类型)非常好,并且不会像 @987654325 那样溢出@ 键入 C。如果您执行 print 200 * 199 * 198 * ... 的明显操作,可能会很慢,但会很准确。同样,加法、减法和模数也是精确的。除法是一个混合包,因为有两个运算符,///,并且它们在 2.x 中发生了变化——通常你只能认为它是不精确的。

      如果您想要更多控制但又不想将自己局限于整数,请查看decimal 模块。

      【讨论】:

        【解决方案5】:

        Python 会自动处理大量数字(与 C 之类的语言不同,例如,您可以溢出其数据类型并将值重置为零) - 在某个点(sys.maxint 或 2147483647)上,它会将整数转换为“long "(用数字后面的L表示),可以是任意长度:

        >>> def fact(x):
        ...     return reduce(lambda x, y: x * y, range(1, x+1))
        ... 
        >>> fact(10)
        3628800
        >>> fact(200)
        788657867364790503552363213932185062295135977687173263294742533244359449963403342920304284011984623904177212138919638830257642790242637105061926624952829931113462857270763317237396988943922445621451664240254033291864131227428294853277524242407573903240321257405579568660226031904170324062351700858796178922222789623703897374720000000000000000000000000000000000000000000000000L
        

        长数字“容易”,浮点数更复杂,几乎所有浮点数的计算机表示都是近似值,例如:

        >>> float(1)/3
        0.33333333333333331
        

        显然你不能在内存中存储无限数量的 3,所以它会作弊并对其进行舍入..

        您可能想查看decimal 模块:

        • 十进制数可以精确表示。相反,像 1.1 这样的数字在二进制浮点中没有精确的表示。最终用户通常不会期望 1.1 显示为 1.1000000000000001,因为它使用二进制浮点数。
        • 与基于硬件的二进制浮点不同,十进制模块具有用户可更改的精度(默认为 28 位),可以根据给定问题的需要进行调整

        【讨论】:

        • @dbr:你的意思是因为Python需要使用二进制数,所以我们得到1.10000000000000000000000001?
        • 1.11 更接近计算机存储的实际值,但从 Python 3.1 开始,它们正在简化表示,以使不知道的人不那么惊讶意识到:docs.python.org/dev/py3k/whatsnew/3.1.html
        【解决方案6】:

        Handling very large numbers in Python

        Python 有一个 BigNum 类来保存 200!并将自动使用它。

        你老师的说法,虽然这里不完全正确,但总的来说是正确的。计算机有局限性,很高兴知道它们是什么。请记住,每次添加另一个整数数据存储时,您可以存储一个大 2^32 (40 亿 +) 倍的数字。很难理解还有多少个数字 - 但是当您添加更多整数来存储一个非常大的数字的确切值时,数学会变得更慢。

        举个例子(你可以用 1000 位存储什么)

        >>> 2 << 1000
        2143017214372534641896850098120003621122809623411067214887500776740702102249872244986396
        7576313917162551893458351062936503742905713846280871969155149397149607869135549648461970
        8421492101247422837559083643060929499671638825347975351183310878921541258291423929553730
        84335320859663305248773674411336138752L
        

        我试图说明用 10000 位甚至 8,000,000 位(一兆字节)可以存储多大的数字,但这个数字有很多页长。

        【讨论】:

        • @Tom:你怎么能测试你不能做 %1 + 200! %?我运行以下代码不成功,虽然是 200!比 1 大 2^32 多:dpaste.com/59409
        • Masi,我认为“另一个存储整数”Tom 的意思是“另外 4 个字节的存储空间”,而不是在现有整数中添加另一个实际整数。
        • 这确实是我的意思。我的观点是,在很小的内存中就有很多可能的组合。例如,宇宙中只有 10^69 个原子,这个数字小于 2^230(奔腾 4 CPU 上的单个 L2 高速缓存行中有 256 个字节)。想象一下 1 MB 内存中有多少。
        猜你喜欢
        • 2018-02-16
        • 1970-01-01
        • 2012-11-13
        • 1970-01-01
        • 2021-08-17
        • 2021-04-05
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        相关资源
        最近更新 更多