【发布时间】:2010-12-06 00:55:18
【问题描述】:
Python 的类型比其他脚本语言更强。例如,在 Perl 中:
perl -E '$c=5; $d="6"; say $c+$d' #prints 11
但在 Python 中:
>>> c="6"
>>> d=5
>>> print c+d
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
TypeError: cannot concatenate 'str' and 'int' objects
Perl 将检查一个字符串并转换为一个数字,+ - / * ** 运算符可以按您对数字的期望工作。 PHP 类似。
Python 使用+ 连接字符串,因此c+d 的尝试操作失败,因为c 是字符串,d 是int。 Python 对numeric types 的感知比 Perl 更强。好的——我可以处理。
但是考虑一下:
>>> from sys import maxint
>>> type(maxint)
<type 'int'>
>>> print maxint
9223372036854775807
>>> type(maxint+2)
<type 'long'>
>>> print maxint+2
9223372036854775809
>>> type((maxint+2)+maxint)
<type 'long'>
>>> print ((maxint+2)+maxint)
18446744073709551616
现在 Python 将 autopromote 从一个 int(在本例中为 64 位长(OS X,python 2.6.1))转换为具有任意精度的 python long int。尽管类型不同,但它们是相似的,Python 允许使用通常的数字运算符。通常这很有帮助。例如,它有助于平滑 32 位和 64 位之间的差异。
从int 到long 的转换是一种方式:
>>> type((maxint+2)-2)
<type 'long'>
转换完成后,对该变量的所有 操作现在都以任意精度完成。任意精度操作比原生 int 操作慢几个数量级。在我正在处理的一个脚本上,我会让一些执行变得很快,而其他的会因此延长到几个小时。考虑:
>>> print maxint**maxint # execution so long it is essentially a crash
所以我的问题是:有没有办法让 Python int 自动升级为 Python long?
编辑,跟进:
我收到了几个 cmet,形式是“你到底为什么想要 C 风格的溢出行为?”问题是这段特殊的代码在 C 和 Perl(使用use int)的 32 位上运行良好,具有 C 的溢出行为。将此代码移植到 Python 的尝试失败。 Python 的不同溢出行为原来是问题的(部分)。该代码混合了许多不同的习语(C、Perl、一些 python)(以及那些 cmets),因此具有挑战性。
本质上,正在进行的图像分析是一个基于圆盘的高通滤波器,用于执行相似的图像比较。高通滤波器的一部分具有两个大多项式的基于整数的乘法。溢出本质上是一种“不在乎,它很大......”的逻辑,因此结果与基于 C 的溢出一样。因此,在 O(n2) 时间中使用霍纳规则是一种浪费,因为较大的多项式只是“大”——carot-top 饱和算法的粗略正义形式。
将基于循环的多项式乘法更改为 FFT 的形式可能要快得多。对于霍纳规则多项式乘法,FFT 的运行时间接近线性,而 O(n2)。从基于磁盘到内存中也将加快这一速度。图像不是特别大,但原始代码是在它们被认为是“巨大的!!!”的时候编写的代码所有者还没有准备好丢弃他心爱的代码,所以我们拭目以待。对他来说,“正确答案”可能只是保留 Perl 或 C,如果他想要那个代码的话。
感谢您的回答。我不知道 Python 的十进制模块,这似乎最接近我的要求——尽管在这种情况下还有其他问题需要解决!
【问题讨论】:
-
maxint**maxint 是一个小数点>>750的数字,我希望你不会对它需要一段时间感到惊讶。还有当数字不适合 32 位时应该发生什么?
-
您是说基本的数学运算使您的应用程序运行时间更长,否则会?这听起来像你的错误,而不是 python 的
-
另外,应该怎么做而不是自动推广?段错误?听起来您应该将数字保持在 sys.maxint 以下...
-
引发 OverflowError 是转换为 long 的完全合理的替代行为,尽管语言中没有这样做的机制(例如,仅针对您的代码而不是库可能没有理智,这意味着它会破坏事物)。
-
@Glenn Maynard:这确实是我一直在寻找的答案。有没有我作为新手看不到的“pythonic”方式或谷歌改变int的默认行为。 Numpy 可能是最接近的,但需要更改大量代码才能到达那里。
标签: python performance integer long-integer