识别无理数或复数

Identify a irrational or complex number

我正在对一个数求平方根,我想知道它是无理数还是复数,return 真还是假

测试用例,对于无理数/复数,取数字的平方根 True,如果平方根是 floatint,则取 False .

[IN 1] 20
[OUT 1] True
[IN 2] 25
[OUT 2] False
[IN 3] -1
[OUT 3] True
[IN 4] -20
[OUT 4] True
[IN 5] 6.25
[OUT 5] False

如何制作实现此功能的函数?

检查一个数是否有复平方根很容易,如果你有一个负数就是这种情况:

def has_complex_sqrt(num):
    return num < 0

然而,要查明一个数是否有无理平方根比较困难。如果您的数字是字符串, 有一种方法可以工作,因为 fractions.Fraction 可以计算出该数字的精确表示。

然后人们利用这样一个事实,即一个数的平方根只有在代表该数的分数的分子和分母的每个素数都有一个 偶数 指数时才是有理数. (网上有很多资源支持这一点)

所以解决这个问题的步骤是:

  • 得到精确的分数表示
  • 找到 prime-factors
  • 然后检查它们是否都有偶数指数。

在代码中实现:

from fractions import Fraction

def get_fraction_from_string(num):
    return Fraction(num)

def get_prime_factors(n):
    # Taken from 
    # you might implement another algorithm here!
    i = 2
    factors = []
    while i * i <= n:
        if n % i:
            i += 1
        else:
            n //= i
            factors.append(i)
    if n > 1:
        factors.append(n)
    return factors

from collections import Counter

def has_even_exponents(primefactorized):
    return all(num % 2 == 0 for num in Counter(primefactorized).values())

最后把这一切合二为一"super-function":

def has_irrational_sqrt(astring):
    fract = get_fraction_from_string(astring)
    primefactors_numerator = get_prime_factors(fract.numerator)
    if not has_even_exponents(primefactors_numerator):
        return True
    primefactors_denominator = get_prime_factors(fract.denominator)
    if not has_even_exponents(primefactors_denominator):
        return True
    return False

为了方便起见,另一个函数检查两者是否为 True:

def has_irrational_or_complex_sqrt(num):
    return has_complex_sqrt(float(num)) or has_irrational_sqrt(num)

现在是交互式测试:

>>> has_irrational_or_complex_sqrt('20')
True
>>> has_irrational_or_complex_sqrt('25')
False
>>> has_irrational_or_complex_sqrt('-1')
True
>>> has_irrational_or_complex_sqrt('-20')
True
>>> has_irrational_or_complex_sqrt('6.25')
False

这会产生预期值。万岁!


如果您的输入已经是 float,此方法可能 行不通!

>>> has_irrational_or_complex_sqrt('0.01')
False
>>> has_irrational_or_complex_sqrt(0.01)  # Oups!
True

但在您的示例中它有效,因为 6.25 可以精确地表示为 float:

>>> has_irrational_or_complex_sqrt(6.25)
False

基于@MSeifert 的回答,但写得更简单:

import collections, fractions
def get_prime_factors(n):
    #
    i = 2
    factors = []
    while i * i <= n:
        if n % i:
            i += 1
        else:
            n //= i
            factors.append(i)
    if n > 1:
        factors.append(n)
    return factors  
def has_irrational_square_root(num):
    #
    frac = fractions.Fraction(str(num))
    top_primes = get_prime_factors(frac.numerator)
    bottom_primes = get_prime_factors(frac.denominator)
    all_even_top = all(num % 2 == 0 for num in collections.Counter(top_primes).values())
    all_even_bottom = all(num % 2 == 0 for num in collections.Counter(bottom_primes).values())
    if all_even_top and all_even_bottom:
        return False
    return True