Python变量负数平方异常:二分法求负数平方根问题排查
问题原因分析
嘿,这问题本质上是两个点:Python运算符优先级的误解,加上对「负数平方根」的数学逻辑认知偏差。
先说说你看到的奇怪现象:
- 直接输入
print(-12**2)得到-144,是因为Python里幂运算**的优先级比一元负号-高,所以实际计算的是-(12**2)——先算12的平方,再加负号。 - 但当
ans=-12.0时,ans**2其实是(-12.0)**2,这是数学上正确的负数平方运算,结果必然是144.0。你之前误以为这两种写法等价,其实运算顺序完全不同,这就是你预期和实际结果不符的核心原因。
再看你的二分逻辑:数学上,任何实数的平方都是非负数,所以当你输入x=-25时,在实数范围内根本不存在一个数ans,使得ans**2 = -25。你的代码里判断ans**2 < x(也就是某个非负数 < -25),这个条件永远不会成立,所以程序会一直把high设为ans,最后收敛到0附近,完全不符合你的预期。
解决方案
要支持负数的平方根求解,我们需要引入复数(因为负数的平方根是虚数)。修改思路很简单:先处理x的符号,对绝对值做二分查找得到实数平方根,再给结果加上虚数单位j。
修改后的代码如下:
x = float(input("Enter a number, whose square root you want to find: ")) epsilon = 0.01 numGuesses = 0 # 处理负数情况,记录符号 is_negative = False if x < 0: is_negative = True x = abs(x) # 原有的二分查找逻辑,针对非负数 low = min(0.0, x) high = max(1.0, x) ans = (high + low)/2.0 while abs(ans**2 - x) >= epsilon: print("low =", low, "high =", high, "ans =", ans) numGuesses += 1 if ans**2 < x: low = ans else: high = ans ans = (high + low)/2.0 # 根据原始符号返回结果 if is_negative: ans = complex(0, ans) print("Number of guesses =", numGuesses) print(ans, "is close to square root of", -x if is_negative else x)
测试输入-25的情况,程序会输出类似5j的结果,这就是-25的平方根(虚数解),完全符合数学定义。
如果你只是想在实数范围内处理(但负数本身没有实平方根),那可以在开头添加判断,提示用户输入非负数,避免无效的逻辑运算。
内容的提问来源于stack exchange,提问作者Pyth0n N00b




