Python的浮点任意精度可用? [英] Python floating point arbitrary precision available?

查看:536
本文介绍了Python的浮点任意精度可用?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

只是为了好玩,因为这很简单,我写了一个简短的程序来生成嫁接数字,但由于浮点精度问题,它没有找到一些大的例子。

  def isGrafting(a): (1,int(ceil(log10(a)))+ 2):
if a == floor((sqrt(a)* 10 **(i-1)) $(1):
if(isGrafting(a) )):
print%d%.15f%(a,sqrt(a))
a + = 1

这段代码错过了至少一个已知的嫁接编号。 9999999998 => 99999.99998999999999949999999994999999999374999999912 ... 在乘以 10 ** 5 之后,它似乎降低了额外的精度。

 >>> a = 9999999998 
>>> sqrt(a)
99999.99999
>>> ((sqrt(a)* 10 **(5))%10 ** int(ceil(log10(a))))
False
>>> ((sqrt(a)* 10 **(5))%10 ** int(ceil(log10(a))))
9999999999.0
>>>打印%.15f%sqrt(a)
99999.999989999996615
>>>打印%.15f%(sqrt(a)* 10 ** 5)
9999999999.000000000000000



<所以我写了一个简短的C ++程序来查看是否我的CPU以某种方式截断了浮点数或python。

 #包括< cstdio> 
#include< cmath>
#include< stdint.h>

int main()
{
uint64_t a = 9999999998;
printf(%ld%.15f%.15f%.15f%.15f \\\
,a,sqrt((double)a),sqrt((double)a)* 1e4,sqrt((double )a)* 1e5,sqrt((double)a)* 1e6);
a = 999999999998;
printf(%ld%.15f%.15f%.15f%.15f\\\
,a,sqrt((double)a),sqrt((double)a)* 1e5,sqrt((double )a)* 1e6,sqrt((double)a)* 1e7);
a = 99999999999998;
printf(%ld%.15f%.15f%.15f%.15f \\\
,a,sqrt((double)a),sqrt((double)a)* 1e6,sqrt((double )a)* 1e7,sqrt((double)a)* 1e8);
返回0;





$ p

  9999999998 99999.999989999996615 999999999.899999976158142 9999999999.000000000000000 99999999990.000000000000000 
999999999998 999999.999998999992386 99999999999.899993896484375 999999999999.000000000000000 9999999999990.000000000000000
99999999999998 9999999.999999899417162 9999999999999.900390625000000 99999999999999.000000000000000 999999999999990.000000000000000
在标准库中, decimal 模块可能是你的重新寻找。另外,我发现 mpmath 是相当有帮助的。 文档也有很多很好的例子(不幸的是我的办公室电脑没有 mpmath installed;否则,我会验证一些例子并发布它们)。



关于 decimal 模块。该模块包含几个用于简单数学运算的内置函数(例如 sqrt ),但是这些函数的结果可能并不总是匹配数学或更高精度的其他模块(尽管它们可能更准确)。例如,

  from decimal import * 
import math

getcontext()。prec = 30
num = Decimal(1)/ Decimal(7)

print(math.sqrt:{0}.format(Decimal(math.sqrt(num))))
print(decimal.sqrt:{0}。format(num.sqrt()))


$ b $在Python 3.2.3中,输出前两行


  math.sqrt:0.37796447300922719758631274089566431939601898193359375 
decimal .sqrt:0.377964473009227227214516536234
实际值:0.3779644730092272272145165362341800608157513118689214

如上所述,不完全是你会期望的,你可以看到精度越高,结果匹配的越少。请注意,在这个例子中,十进制模块确实有更高的精度,因为它更接近匹配实际值

Just for fun and because it was really easy, I've written a short program to generate Grafting numbers, but because of floating point precision issues it's not finding some of the larger examples.

def isGrafting(a):
  for i in xrange(1, int(ceil(log10(a))) + 2):
    if a == floor((sqrt(a) * 10**(i-1)) % 10**int(ceil(log10(a)))):
      return 1

a = 0
while(1):
  if (isGrafting(a)):
    print "%d %.15f" % (a, sqrt(a))
  a += 1

This code misses at least one known Grafting number. 9999999998 => 99999.99998999999999949999999994999999999374999999912... It seems to drop extra precision after multiplying by 10**5.

>>> a = 9999999998
>>> sqrt(a)
99999.99999
>>> a == floor((sqrt(a) * 10**(5)) % 10**int(ceil(log10(a))))
False
>>> floor((sqrt(a) * 10**(5)) % 10**int(ceil(log10(a))))
9999999999.0
>>> print "%.15f" % sqrt(a)
99999.999989999996615
>>> print "%.15f" % (sqrt(a) * 10**5)
9999999999.000000000000000

So I wrote a short C++ program to see if it was my CPU truncating the floating point number or python somehow.

#include <cstdio>
#include <cmath>
#include <stdint.h>

int main()
{
  uint64_t a = 9999999998;
  printf("%ld %.15f %.15f %.15f %.15f\n", a, sqrt((double)a), sqrt((double)a)*1e4, sqrt((double)a)*1e5, sqrt((double)a)*1e6);
  a = 999999999998;
  printf("%ld %.15f %.15f %.15f %.15f\n", a, sqrt((double)a), sqrt((double)a)*1e5, sqrt((double)a)*1e6, sqrt((double)a)*1e7);
  a = 99999999999998;
  printf("%ld %.15f %.15f %.15f %.15f\n", a, sqrt((double)a), sqrt((double)a)*1e6, sqrt((double)a)*1e7, sqrt((double)a)*1e8);
  return 0;
}

Which outputs:

9999999998 99999.999989999996615 999999999.899999976158142 9999999999.000000000000000 99999999990.000000000000000
999999999998 999999.999998999992386 99999999999.899993896484375 999999999999.000000000000000 9999999999990.000000000000000
99999999999998 9999999.999999899417162 9999999999999.900390625000000 99999999999999.000000000000000 999999999999990.000000000000000

So it looks like I'm running up hard against the limits of floating point precision and the CPU is chopping off the remaining bits because it thinks that the remaining difference is floating point error. Is there a way to work around this under Python? Or do I need to move to C and use GMP or something?

解决方案

In the standard library, the decimal module may be what you're looking for. Also, I have found mpmath to be quite helpful. The documentation has many great examples as well (unfortunately my office computer does not have mpmath installed; otherwise I would verify a few examples and post them).

One caveat about the decimal module, though. The module contains several in-built functions for simple mathematical operations (e.g. sqrt), but the results from these functions may not always match the corresponding function in math or other modules at higher precisions (although they may be more accurate). For example,

from decimal import *
import math

getcontext().prec = 30
num = Decimal(1) / Decimal(7)

print("   math.sqrt: {0}".format(Decimal(math.sqrt(num))))
print("decimal.sqrt: {0}".format(num.sqrt()))

In Python 3.2.3, this outputs the first two lines

   math.sqrt: 0.37796447300922719758631274089566431939601898193359375
decimal.sqrt: 0.377964473009227227214516536234
actual value: 0.3779644730092272272145165362341800608157513118689214

which as stated, isn't exactly what you would expect, and you can see that the higher the precision, the less the results match. Note that the decimal module does have more accuracy in this example, since it more closely matches the actual value.

这篇关于Python的浮点任意精度可用?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆