为何判断完全平方数时pow(math.sqrt(n),2)==n不如math.sqrt(n)%1==0可靠?
完全平方数判断的浮点数精度问题
问题描述
在编程测试网站做题时,我写出了以下代码:
import math def solution(n): return pow(math.sqrt(n)+1,2) if (pow(math.sqrt(n),2) == n) else -1
测试结果正确率仅为87%,后来发现把判断条件换成if(math.sqrt(n)% 1 == 0)就能通过测试,想知道第一种方法不可行的原因。
原因分析
问题核心在于浮点数的精度限制:
- Python里的
float是双精度浮点数,只能精确表示2^53范围内的整数。当n是超出这个范围的完全平方数时,math.sqrt(n)返回的浮点数无法精确对应原本的整数平方根,会存在微小偏差。 - 比如某个大整数
k²,math.sqrt(k²)得到的结果可能是k ± 1e-15这类近似值,用pow再平方回去后,得到的数值会和原n有细微差异,导致pow(math.sqrt(n),2) == n的判断结果为False,哪怕n确实是完全平方数。 - 而
math.sqrt(n)%1 == 0的逻辑是判断平方根的小数部分是否为0。当平方根的浮点数表示存在微小误差时,只要整数部分准确,小数部分会趋近于0,在浮点数取模运算的精度范围内会被判定为0,因此能正确识别完全平方数。
更可靠的写法
如果使用Python 3.8及以上版本,推荐用math.isqrt直接获取整数平方根,彻底规避浮点数精度问题:
import math def solution(n): k = math.isqrt(n) return (k + 1) ** 2 if k * k == n else -1
内容的提问来源于stack exchange,提问作者daundawndown
相关产品推荐
相关产品推荐

