当它们在数学上相同时有两个不同的答案..?
Two different answers when they are mathematically the same..?
我在我的程序中遇到了一个错误,该错误正在执行重新排列方法来查找方程的根。
我注意到 Python 根据括号产生了两个不同的答案。
例如
-4**(1/3) = -1.5874010519681994
-4.0**(1/3) = -1.5874010519681994
(-4)**(1/3) = (0.7937005259840999+1.3747296369986024j)
(-4.0)**(1/3) = (0.7937005259840999+1.3747296369986024j)
我已将 -4.0 分配给变量 x,然后将 x**(1/3) 分配给 y,但是我得到的是复数而不是实际答案。
这是为什么?有没有一种简单的方法可以防止这种情况发生?
谢谢
这不是错误,而是运算符优先级的问题。如果您检查 the docs,您会看到减号运算符 -
的优先级低于求幂运算符 **
。因此,您的第一个表达式是:
- (4 ** (1/3))
第二个是:
(-4) ** (1/3)
这根本不是一回事。
您的示例中发生了两件事。
首先,-4
两边的括号很重要,因为按运算顺序求幂是在取反之前完成的。因此,在您的前两个示例中,首先完成功率,然后对功率结果取负值。这是你所期望的,所以你没有查询它,但这并没有取 -4
的立方根,而是 4
.
的立方根的负数
第二个问题是Python中的大多数浮点运算并不精确。 1/3
的结果不是分数而是浮点数。如果对存储 1/3
值的变量使用 as_integer_ratio
方法,您将得到结果
(6004799503160661, 18014398509481984)
表明它实际上不是 3 的 1。因此,取某物的 1/3
次方与取其立方根不同,因为实际上不涉及这样的分数。 Python 将指数解释为实数,而不是有理数,对于负数作为底数,x**y
的值被解释为 exp(y*ln(x))
,就像在数学中所做的那样。负实数的对数是复数,所以最后的结果也是复数。
如果你真的想要 -4
的立方根,你可以像前两个例子那样编写你的计算。如果你想对一般可能的负数求根,你可以写一个例程,定义为
def power_frac(base, numerator, denominator):
"""Return base**(numerator/denominator) where base is a
floating-point number and both numerator and denominator are
integers.
"""
此函数需要检查许多情况,因为(例如)负数的偶数根不是实数。但这是可以做到的。我不相信 Python 中包含这样的功能。请记住,指数必须以两个整数(或分数值)的形式给出,因为 Python 无法计算出将指数计算为浮点除法时所指的确切分数。
如果你只想要任何实数的立方根,你可以使用
def cuberoot(x):
return x**(1/3) if x >= 0 else -(-x)**(1/3)
我在我的程序中遇到了一个错误,该错误正在执行重新排列方法来查找方程的根。
我注意到 Python 根据括号产生了两个不同的答案。 例如
-4**(1/3) = -1.5874010519681994
-4.0**(1/3) = -1.5874010519681994
(-4)**(1/3) = (0.7937005259840999+1.3747296369986024j)
(-4.0)**(1/3) = (0.7937005259840999+1.3747296369986024j)
我已将 -4.0 分配给变量 x,然后将 x**(1/3) 分配给 y,但是我得到的是复数而不是实际答案。
这是为什么?有没有一种简单的方法可以防止这种情况发生?
谢谢
这不是错误,而是运算符优先级的问题。如果您检查 the docs,您会看到减号运算符 -
的优先级低于求幂运算符 **
。因此,您的第一个表达式是:
- (4 ** (1/3))
第二个是:
(-4) ** (1/3)
这根本不是一回事。
您的示例中发生了两件事。
首先,-4
两边的括号很重要,因为按运算顺序求幂是在取反之前完成的。因此,在您的前两个示例中,首先完成功率,然后对功率结果取负值。这是你所期望的,所以你没有查询它,但这并没有取 -4
的立方根,而是 4
.
第二个问题是Python中的大多数浮点运算并不精确。 1/3
的结果不是分数而是浮点数。如果对存储 1/3
值的变量使用 as_integer_ratio
方法,您将得到结果
(6004799503160661, 18014398509481984)
表明它实际上不是 3 的 1。因此,取某物的 1/3
次方与取其立方根不同,因为实际上不涉及这样的分数。 Python 将指数解释为实数,而不是有理数,对于负数作为底数,x**y
的值被解释为 exp(y*ln(x))
,就像在数学中所做的那样。负实数的对数是复数,所以最后的结果也是复数。
如果你真的想要 -4
的立方根,你可以像前两个例子那样编写你的计算。如果你想对一般可能的负数求根,你可以写一个例程,定义为
def power_frac(base, numerator, denominator):
"""Return base**(numerator/denominator) where base is a
floating-point number and both numerator and denominator are
integers.
"""
此函数需要检查许多情况,因为(例如)负数的偶数根不是实数。但这是可以做到的。我不相信 Python 中包含这样的功能。请记住,指数必须以两个整数(或分数值)的形式给出,因为 Python 无法计算出将指数计算为浮点除法时所指的确切分数。
如果你只想要任何实数的立方根,你可以使用
def cuberoot(x):
return x**(1/3) if x >= 0 else -(-x)**(1/3)