Python:计算点后两位数(浮点、小数或其他)的最快方法



正如我所发现的,十进制更精确是以处理能力为代价的。我发现

getcontext().prec = 2
Decimal(number)

还计算点之前的数字。在我的情况下,无论数字有多大,我只需要它来计算点后的两个数字。因为有时我得到的数字是12345.15,有时是2.53。如果数字是5或298.1呢?

我对浮点、小数、四舍五入和截断之间的所有这些区别有点困惑。

我的主要问题是:

我如何用254.12或15.35这样的数字以最少的资源成本进行计算?也许甚至有可能伪造这些数字?四舍五入并不重要,但用浮点和点后的8位数字进行计算,然后截断它们对我来说似乎是浪费资源。如果我错了,请纠正我。

我也知道如何使用进行基准测试

import time
start_time = time.clock()
main()
print time.clock() - start_time, "seconds"

但是我确信有足够多的事情我不知道。由于我对编程还很陌生,如果有人能给我一些提示,让我用一段代码来工作和学习,我会很高兴。感谢您花时间阅读本文!:)

首先,请注意浮点运算并不一定像您担心的那样昂贵。这将取决于您使用的CPU,但例如,由于流水线的原因,以整数为主的程序中的单个浮点运算的成本将与整数运算的成本一样高。这就像去夜店的洗手间。女生卫生间总是有一条线——整数操作——但男生从来没有——浮点操作。

另一方面,低功耗CPU甚至可能根本不包括浮点支持,这使得任何浮点操作都非常昂贵!所以,在判断应该使用浮点运算还是整数运算之前,先进行一些分析。您提到使用time.clock并比较开始和结束时间。您应该了解一下python附带的timeit模块。

然而,比糟糕的性能更糟糕的是,浮点数并不总是代表您想要的数字。不管小数点是多少,如果一个数字足够大,或者你对它做了错误的运算,你最终可能会得到一个浮点值,它"近似"了你的结果,而没有准确地存储它。

如果您知道您的应用程序需要小数以外的两位数字,我建议您编写一个类来使用整数实现这种行为。Python的整数在变大时会自动转换为大数字,并且精度是精确的。因此存在性能损失(bignum操作比高端硬件上的整数或浮点操作慢)。但你可以保证你想要的任何行为。

如果您的申请是财务申请,请注意,您将不得不花一些时间处理舍入问题。每个人都看过《超人3》,现在他们认为你在偷他们的0.00001美分。。。

在Python中,无论精度如何,所有浮点都是相同的大小,因为它们都用一个"double"类型表示。这意味着无论哪种方式,您都将"浪费"内存(实际上,24字节是一个微小的量)。使用sys.getsizeof显示:

>>> import sys
>>> sys.getsizeof(8.13333333)
24
>>> sys.getsizeof(8.13)
24

这也体现在这样一个事实上:如果int太大(int没有最大值),它就不能转换为float——你会得到一个OverflowError:

>>> 2**1024 + 0.5
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
OverflowError: long int too large to convert to float

即使精度设置正确,使用Decimal的效率也更低。这是因为类实例本身占用了大量空间,而与它们的内容无关:

>>> import decimal
>>> sys.getsizeof(decimal.Decimal(0))
80

prec设置实际上会影响总位数,而不仅仅是小数点后的位数。关于这一点,文件显示

一个新的十进制数的意义仅由数字决定的数字输入。上下文精度和舍入只起作用在算术运算期间。

以及

quantize()方法将一个数字四舍五入为一个固定指数。这种方法对于经常将结果舍入为固定位置

因此,如果你需要在点后使用固定数量的数字,你可以寻找以下几点。

关于性能,在我看来,您过早地优化了。通常,您不需要担心最快的方法来进行不到一微秒的计算(当然,除非您需要每秒进行数百万次这样的计算)。在快速基准测试中,两个数字的总和对于float s需要48纳秒,对于Decimal s需要82纳秒。这种差异对大多数应用程序的影响应该很小。

最新更新