在 Python 中停止复数除法中的近似
Stop Approximation in Complex Division in Python
我一直在编写一些代码来列出 Python 中有理整数的高斯整数除数。 (与欧拉计划问题153相关)
我似乎在某些数字上遇到了一些麻烦,我相信这与 Python 近似复数除法有关。
这是我的函数代码:
def IsGaussian(z):
#returns True if the complex number is a Gaussian integer
return complex(int(z.real), int(z.imag)) == z
def Divisors(n):
divisors = []
#Firstly, append the rational integer divisors
for x in range(1, int(n / 2 + 1)):
if n % x == 0:
divisors.append(x)
#Secondly, two for loops are used to append the complex Guassian integer divisors
for x in range(1, int(n / 2 + 1)):
for y in range(1, int(n / 2 + 1)):
if IsGaussian(n / complex(x, y)) == n:
divisors.append(complex(x, y))
divisors.append(complex(x, -y))
divisors.append(n)
return divisors
当我 运行 Divisors(29)
我得到 [1, 29]
,但是这漏掉了其他四个除数,其中一个是 (5 + 2j),可以清楚地看到分成29.
在 运行 宁 29 / complex(5, 2)
,Python 给出 (5 - 2.0000000000000004j)
这个结果不正确,应该是 (5 - 2j)
。有什么办法可以绕过 Python 的近似值吗?为什么这个问题对于 100 以下的许多其他有理整数没有上升?
在此先感谢您的帮助。
您可以定义一个 epsilon,通过使用 round
舍入到所需的小数位数 places/precision(例如 10):
def IsGaussian(z, prec=10):
# returns True if the complex number is a Gaussian integer
# rounds the input number to the `prec` number of digits
z = complex(round(z.real,prec), round(z.imag,prec))
return complex(int(z.real), int(z.imag)) == z
不过您的代码还有另一个问题:
if IsGaussian(n / complex(x, y)) == n:
这只会给出 n = 0
或 n = 1
的结果。您可能想删除相等性检查。
在内部,CPython 对复数使用一对双精度浮点数。一般来说,数值解的行为过于复杂,无法在此总结,但在数值计算中,一些错误是不可避免的。
EG:
>>>print(.3/3)
0.09999999999999999
因此,在测试此类解决方案时,使用近似相等而不是实际相等通常是正确的。
isclose function in the cmath module 正是出于这个原因。
>>>print(.3/3 == .1)
False
>>>print(isclose(.3/3, .1))
True
这类问题是Numerical Analysis的领域;对于有关此主题的进一步问题,这可能是一个有用的标签。
请注意,函数标识符被认为是 'pythonic' snake_case。
from cmath import isclose
def is_gaussian(z):
#returns True if the complex number is a Gaussian integer
rounded = complex(round(z.real), round(z.imag))
return isclose(rounded, z)
我一直在编写一些代码来列出 Python 中有理整数的高斯整数除数。 (与欧拉计划问题153相关)
我似乎在某些数字上遇到了一些麻烦,我相信这与 Python 近似复数除法有关。
这是我的函数代码:
def IsGaussian(z):
#returns True if the complex number is a Gaussian integer
return complex(int(z.real), int(z.imag)) == z
def Divisors(n):
divisors = []
#Firstly, append the rational integer divisors
for x in range(1, int(n / 2 + 1)):
if n % x == 0:
divisors.append(x)
#Secondly, two for loops are used to append the complex Guassian integer divisors
for x in range(1, int(n / 2 + 1)):
for y in range(1, int(n / 2 + 1)):
if IsGaussian(n / complex(x, y)) == n:
divisors.append(complex(x, y))
divisors.append(complex(x, -y))
divisors.append(n)
return divisors
当我 运行 Divisors(29)
我得到 [1, 29]
,但是这漏掉了其他四个除数,其中一个是 (5 + 2j),可以清楚地看到分成29.
在 运行 宁 29 / complex(5, 2)
,Python 给出 (5 - 2.0000000000000004j)
这个结果不正确,应该是 (5 - 2j)
。有什么办法可以绕过 Python 的近似值吗?为什么这个问题对于 100 以下的许多其他有理整数没有上升?
在此先感谢您的帮助。
您可以定义一个 epsilon,通过使用 round
舍入到所需的小数位数 places/precision(例如 10):
def IsGaussian(z, prec=10):
# returns True if the complex number is a Gaussian integer
# rounds the input number to the `prec` number of digits
z = complex(round(z.real,prec), round(z.imag,prec))
return complex(int(z.real), int(z.imag)) == z
不过您的代码还有另一个问题:
if IsGaussian(n / complex(x, y)) == n:
这只会给出 n = 0
或 n = 1
的结果。您可能想删除相等性检查。
在内部,CPython 对复数使用一对双精度浮点数。一般来说,数值解的行为过于复杂,无法在此总结,但在数值计算中,一些错误是不可避免的。
EG:
>>>print(.3/3)
0.09999999999999999
因此,在测试此类解决方案时,使用近似相等而不是实际相等通常是正确的。
isclose function in the cmath module 正是出于这个原因。
>>>print(.3/3 == .1)
False
>>>print(isclose(.3/3, .1))
True
这类问题是Numerical Analysis的领域;对于有关此主题的进一步问题,这可能是一个有用的标签。
请注意,函数标识符被认为是 'pythonic' snake_case。
from cmath import isclose
def is_gaussian(z):
#returns True if the complex number is a Gaussian integer
rounded = complex(round(z.real), round(z.imag))
return isclose(rounded, z)