gmpy2 log2 16位数字后不正确 [英] gmpy2 log2 not accurate after 16 digits

查看:239
本文介绍了gmpy2 log2 16位数字后不正确的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

在gmpy2中使用log2()时,16位数字后似乎不准确.它似乎可以15位数字正常工作,但之后使用mpz(mpfr(2)** mpfr(x))答案不正确.我需要改变精度吗?我认为python本身最多可以精确到53位数字.

When using log2() in gmpy2 it does not seem to be accurate after 16 digits. It seems to work fine at 15 digits but after that the answer is not correct using mpz(mpfr(2) ** mpfr(x)). Do I need change the precision? I thought python by itself would be accurate up to 53 digits.

另外,gmpy2中还有一种方法可以在10和2以外的底数中使用对数运算吗?例如,以8或16为底.

Additionally, is there a way in gmpy2 to use a logarithm operation in bases besides 10 and 2? For example, base 8 or 16.

推荐答案

标准的Python浮点类型精确到53位,大约是16个十进制数字. gmpy2使用默认精度53位.如果想要更准确的结果,则需要提高精度.

The standard Python float type is accurate to 53 bits which is roughly 16 decimal digits. gmpy2 uses a default precision of 53 bits. If you want more accurate results, you will need to increase the precision.

>>> import gmpy2
>>> from gmpy2 import mpz,mpfr,log2
>>> a=12345678901234567890
>>> gmpy2.get_context().precision=70
>>> mpz(2**log2(a))
mpz(12345678901234567890L)

要计算不同的对数,只需使用

To calculate a logarithm in a different, just use

>>> gmpy2.log(x)/gmpy2.log(base)

更新

通常不可能从一系列浮点计算中恢复出精确的整数结果.根据实际计算,可以提高精度,直到获得足够接近"为止.

Recovering an exact integer result from a sequence of floating point calculations is generally not possible. Depending on the actual calculations, you can increase the precision until you get "close enough".

让我们看一下精度的影响.请注意,a的长度为57位,因此无法用53位的浮点精度来精确表示.

Let's look at the impact of precision. Note that a is 57 bits long so it cannot be exactly represented with 53 bits of floating point precision.

>>> a=123543221556677776
>>> a.bit_length()
57
>>> gmpy2.get_context().precision=53
>>> mpfr(a);2**log2(a)
mpfr('1.2354322155667778e+17')
mpfr('1.2354322155667752e+17')

由于将二进制浮点数转换为十进制会引入转换错误,因此请以二进制形式查看结果.

Since conversion of a binary floating point number to decimal can introduce a conversion error, lets look at the results in binary.

>>> mpfr(a).digits(2);(2**log2(a)).digits(2)
('11011011011101001111001111100101101001011000011001001', 57, 53)
('11011011011101001111001111100101101001011000010111001', 57, 53)

让我们尝试将精度提高到57位.

Let's trying increasing the precision to 57 bits.

>>> gmpy2.get_context().precision=57
>>> mpfr(a).digits(2);(2**log2(a)).digits(2)
('110110110111010011110011111001011010010110000110010010000', 57, 57)
('110110110111010011110011111001011010010110000110010011000', 57, 57)

请注意,更多位是正确的,但是仍然存在错误.让我们尝试64位.

Notice more bits are correct but there is still an error. Let's try 64 bits.

>>> gmpy2.get_context().precision=64
>>> mpfr(a);2**log2(a)
mpfr('123543221556677776.0',64)
mpfr('123543221556677775.953',64)
>>> mpfr(a).digits(2);(2**log2(a)).digits(2)
('1101101101110100111100111110010110100101100001100100100000000000', 57, 64)
('1101101101110100111100111110010110100101100001100100011111111010', 57, 64)

尾随1的数量很大,大约等于十进制的尾随9.

The large number of trailing 1's is roughly equivalent to trailing 9's in decimal.

一旦足够接近",您可以将其转换为整数,从而将结果舍入到期望值.

Once you get "close enough", you can convert to an integer which will round the result to the expected value.

为什么57位不够? gmpy2使用的 MPFR 库确实执行正确的舍入.仍然有一个小错误.我们还使用正确舍入后的值上方和下方的浮点值查看结果.

Why isn't 57 bits sufficient? The MPFR library that is used by gmpy2 does perform correct rounding. There is still a small error. Let's also look at the results using the floating point values immediately above and below the correctly rounded value.

>>> gmpy2.get_context().precision=57
>>> b=log2(a)
>>> 2**gmpy2.next_below(b);2**log2(a);2**gmpy2.next_above(b)
mpfr('123543221556677746.0',57)
mpfr('123543221556677784.0',57)
mpfr('123543221556677822.0',57)

请注意,即使b的很小变化也会导致2**b的更大变化.

Notice that even a small change in b causes a much larger change in 2**b.

更新2

浮点算术只是实数的数学特性的近似值.一些数字是有理数(可以写为小数),但是大多数数字是非理性的(它们永远不能写成小数).浮点算术实际上使用对数字的有理逼近.

Floating point arithmetic is only an approximation to the mathematical properties of real numbers. Some numbers are rational (they can be written as a fraction) but most numbers are irrational (they can never be written exactly as a fraction). Floating point arithmetic actually uses a rational approximation to a number.

以下我跳过了一些细节-我假设所有数字都在0到1之间.

I've skipped some of the details in the following - I assume all numbers are between 0 and 1.

对于二进制浮点数(大多数计算机使用的是),有理逼近的分母必须为2的幂.可以精确表示类似1/21/4的数字.小数浮点使用有理数逼近,其分母为10的幂.1/2,'1/4','1/5'和1/20之类的数字都可以精确表示.都不能完全代表1/3.以6为基数的浮点算术实现可以准确表示1/21/3,但不能表示1/10.特定格式的精度仅指定分子的最大大小.总会有一些有理数不能用给定的基数精确表示.

With binary floating point (what most computers use), the denominator of the rational approximation must be a power of 2. Numbers like 1/2 or 1/4 can be represented exactly. Decimal floating point uses rational approximations that have a denominator that is a power of 10. Numbers like 1/2, '1/4', '1/5', and 1/20 can all be represented exactly. Neither can represent 1/3 exactly. A base-6 implementation of floating point arithmetic can represent 1/2 and 1/3 exactly but not 1/10. The precision of a particular format just specifies the maximum size of the numerator. There will always be some rational numbers that cannot be represented exactly by a given base.

由于无理数不能写为有理数,所以不能用给定的基数精确表示它们.由于对数和指数函数几乎总是导致不合理的值,因此计算几乎从不精确.通过提高精度,通常可以足够接近",但永远无法保证精确.

Since irrational numbers can't be written as a rational number, they can not be represented exactly by a given base. Since logarithm and exponential functions almost always result in irrational values, the calculations are almost never exact. By increasing the precision, you can usually get "close enough" but you can never get exact.

有些程序可以工作symbolically-他们记得alog2(n),当您执行2**a时,将返回a的确切值.参见 SymPy .

There are programs that work symbolically - they remember that a is log2(n) and when you do 2**a, the exact value of a is returned. See SymPy.

这篇关于gmpy2 log2 16位数字后不正确的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

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