【问题标题】:How to get largest possible precision? (Python - Decimal)如何获得最大可能的精度? (Python - 十进制)
【发布时间】:2023-03-08 13:36:01
【问题描述】:

我将Decimal 类用于需要精度的操作。

我想使用“尽可能大”的精度。有了这个,我的意思是尽可能精确地运行程序的系统可以处理。

要设置一定的精度很简单:

import decimal
decimal.getcontext().prec = 123 #123 decimal precision

我试图找出“十进制”类可以计算的最大精度:

print(decimal.MAX_PREC)
>> 999999999999999999

所以我尝试将精度设置为最大精度(知道它可能不起作用..):

decimal.getcontext().prec = decimal.MAX_PREC

但是,当然,这会引发 内存错误(在除法上)

所以我的问题是:如何确定当前系统可以处理的最大精度?

额外信息:

import sys
print(sys.maxsize)
>> 9223372036854775807

【问题讨论】:

  • 您的系统可能有内存可用于一些精度为 X 的对象,但不是很多。因此,没有一个单一的答案——在内存耗尽之前您可以使用的最大精度取决于您要进行的计算。
  • 我尝试做你所做的,它不会引发任何内存错误并改变精度。你的python版本是什么?另外,你可能想看看this answer
  • @RickM。我使用的是python 3.6.5(64位),你有没有试过用无限的非重复小数做除法或其他东西?
  • @Eli 当然,你可以期待 MemoryError 但这并不意味着没有设置精度(正如 Eric Postpischii 所说)。正如您现在的问题,您应该在除法上添加内存错误以使事情更清楚。
  • @RickM。我已经编辑了问题,但问题并没有太大变化,只是想要一种尽可能精确的方法......

标签: python memory floating-point decimal precision


【解决方案1】:

试图这样做是错误的。对问题投入更高的精度对于浮点新手来说是一个诱人的陷阱,但它并没有那么有用,尤其是在这种极端情况下。

您的操作实际上并不需要“尽可能大”的精度,即使这是一个定义明确的概念。它们要么需要精确 算术,在这种情况下decimal.Decimal 完全是错误的工具,您应该研究fractions.Fraction 或符号计算之类的东西,或者它们不需要那么高的精度,而您应该确定您实际需要多少精度并使用它。

如果您仍然想尽可能精确地解决问题,那么实际的精确度将取决于您正在做什么样的数学,以及您尝试存储多少精确到荒谬的数字一下子记忆。这可以通过分析您的程序和Decimal 对象的内存需求来确定,或者您可以改为将精度作为参数并二进制搜索不会导致崩溃的最大精度。

【讨论】:

  • 这绝对是正确的答案。您需要非常少的位数来计算诸如到 Alpha Centauri 的精确距离(以毫米为单位)(只有大约 20 个十进制数字,仅略超出正常 64 位整数的范围)。我认为可以肯定地说,在任何实际应用中,您的测量误差都将超过因缺乏Decimal 精度而导致的任何数字误差。
  • @user2357112,这不是错误,而是教育。当然我不需要无限的精度,但是如果我发现了一个新的常数呢?并想发布一个使用“无限”精度的应用程序。如果我只想在 pi 中找到比已经找到的更多的数字怎么办?如果我想测试 e 或 Mill 常数的不合理性怎么办。如果我可以制作一个尽可能精确的程序,直到由于内存或其他原因而无法实现。NASA 只使用 15 位 pi,因为它足够准确,但人们仍然试图获得更多,我在这里努力使这成为可能。
  • @Eli:在问题上投入尽可能高的精度实际上对您列出的任何内容都没有帮助。例如,计算 pi 的最新技术不仅仅涉及在任意精度的浮点实现中抛出精度;它看起来像this,它根据计算的实际需要来管理精度。 (此外,它知道如何智能地使用磁盘空间,而不是局限于内存或操作系统级别的交换。)
  • 至于合理性测试,再多的精度也无法让您通过直接计算来测试 e 或 Mill 常数的不合理性(而且我认为无论如何我们都不确定如何计算 Mill 常数)。
  • 试图突破高精度计算的极限是一个值得的目标,但它不是这样工作的。
【解决方案2】:

我想推荐一个函数,它可以让您以蛮力的方式估计给定操作的最大精度:

def find_optimum(a,b, max_iter):
    for i in range(max_iter):
        print(i)
        c = int((a+b)/2)
        decimal.getcontext().prec = c
        try:
            dummy = decimal.Decimal(1)/decimal.Decimal(7) #your operation
            a = c
            print("no fail")
        except MemoryError:
            print("fail")
            dummy = 1
            b = c
        print(c)
        del dummy

这只是一次将间隔减半,并查看是否发生错误。使用max_iter=10a=int(1e9), b=int(1e11) 调用会得到:

>>> find_optimum(int(1e9), int(1e11), 10)
0
fail
50500000000
1
no fail
25750000000
2
no fail
38125000000
3
no fail
44312500000
4
fail
47406250000
5
fail
45859375000
6
no fail
45085937500
7
no fail
45472656250
8
no fail
45666015625
9
no fail
45762695312

这可能会让您大致了解您正在处理的内容。这在 i5-3470 和 16GB RAM 上花费了大约半小时,所以你真的只会将它用于测试目的。

我不认为有一种实际的精确方法可以为您的操作获得最大精度,因为您必须准确了解内存使用对内存消耗的依赖性。我希望这至少对您有所帮助,而且我真的很想知道,您需要这种精度来做什么。

编辑我觉得这确实需要添加,因为我在这里阅读了您的 cmets 评分最高的帖子。以这种方式使用任意高精度不是人们计算常数的方式。您将编写一些程序,以一种巧妙的方式利用磁盘空间(例如计算 RAM 中的一堆数字并将这些数字写入文本文件),但永远不要只使用 RAM/swap,因为这总是会限制您的结果。使用现代算法来计算 pi,您不需要无限的 RAM,您只需在机器中放入另一个 4TB 硬盘并让它写入下一个数字。到目前为止的数学常数。

现在是物理常数:它们并不精确。他们依靠测量。我不太确定 atm(将编辑),但我认为 最准确 物理常数的误差为 10**(-8)。对它投入更高的精度,并不能使它更精确,你只会计算出更多的错误数字。

不过,作为一个实验,这是一个有趣的想法,这就是我什至首先发布答案的原因。

【讨论】:

  • 这正是我能做的,计算 X 位数并将其刷新到硬盘驱动器,甚至不必是文本文件,二进制文件也可以。但问题是 RAM 比 HDD 快。因此,计算下一个数字并写入它比计算数百万个数字并将它们刷新到文件中更乏味。但我很高兴这个问题得到了一些关注。
  • 如果您使用 RAM 作为缓冲区,在写入磁盘之前,没关系
【解决方案3】:

Decimal 类的最大精度是设备内存的一个函数,因此对于一般情况没有设置它的好方法。基本上,您将机器上的所有内存分配给一个变量以获得最大精度。

如果数学运算支持它,长整数将为您提供无限的精度。但是,您只能使用整数。

加法、减法、乘法和简单的指数可以完全用长整数来执行。

在 Python 3 之前,内置的 long 数据类型将执行任意精度计算。 https://docs.python.org/2/library/functions.html#long

在 Python >=3 中,int 数据类型现在表示长整数。 https://docs.python.org/3/library/functions.html#int

64 位整数数学的一个示例是实现是 bitcoind,其中交易计算需要精确值。但是,比特币交易的精确度被限制在 1 个“Satoshi”;每个比特币被定义为 10^8(整数)个 Satoshi。

Decimal 类的工作原理类似。 10^-8 的小数精度类似于 Bitcoin-Satoshi 范式。

【讨论】:

    【解决方案4】:

    根据您上面的回复:

    如果我只想在 pi 中找到比已经找到的更多的数字怎么办?如果我想测试 e 或 Mill 常数的非理性怎么办?

    我明白了。我真的。我几年前的one SO question 是关于 Python 的任意精度浮点库的。如果这些是您想要生成的数字表示类型,请为深入研究做好准备。 Decimal/FP 算术在计算机科学中是 notoriously tricky

    一些程序员在遇到问题时会想“我知道,我会使用浮点运算”。现在他们有 1.999999999997 个问题。 – @tomscott

    我认为,当其他人说这是一个“错误”或“取决于”时,想知道给定平台上 Python Decimal 类型的最大精度是多少时,他们比我猜测的更直接地回答了您的问题是有意的。您询问了 Python Decimal 类型,但如果您对用于教育目的的 FP 算术感兴趣——“在 pi 中查找更多数字”——您将需要比 Decimal 或 @ 更强大、更灵活的工具987654325@。这些内置的 Python 类型甚至都没有close。这些对于 NASA 来说可能已经足够了,但它们有限制……事实上,正是你所询问的限制。

    这就是多精度(或arbitrary-precision)浮点库的用途:任意精确的表示。想要计算未来 20 年的 pi? Python 的 Decimal 类型甚至无法让您度过day

    事实上,多精度二进制 FP 算术仍然是一种边缘科学。对于 Python,您需要在 Linux 机器上安装 GNU MPFR 库,然后您可以使用 Python 库 gmpy2 尽可能深入地研究。

    那么,问题不是“我的程序可以使用的最大精度是多少?”

    它是,“我如何编写我的程序,以便它可以运行直到停电?”

    这是另外一个问题,但至少它受到算法的限制,而不是它运行的硬件。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2016-12-19
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多