Почему Python не работает с системами счисления, основания которых превышают 36?

Рейтинг: 2Ответов: 3Опубликовано: 15.02.2023

Вот программа, печатающая элементы последовательности A235395, не превышающие 4000:

# Here's a Python program that checks for prime numbers 
# whose decimal representation is also a valid number 
# in base 9 and interpreted as such is again a prime,
# and prints such numbers less than 4000:

def is_prime(n):
    """Check if a number is prime."""
    if n < 2:
        return False
    for i in range(2, int(n**0.5) + 1):
        if n % i == 0:
            return False
    return True

def is_valid_base_9(n):
    """Check if a number is valid in base 9."""
    digits = str(n)
    for digit in digits:
        if int(digit) >= 9:
            return False
    return True

primes_base_9 = []
for n in range(2, 4000):
    if is_prime(n) and is_valid_base_9(n) and is_prime(int(str(n), 9)):
        primes_base_9.append(n)

print(primes_base_9)

Допустим, я желаю изменить эту программу таким образом, чтобы она работала не с 9-чной, а с 37-чной системой счисления. Оказывается, я не могу этого сделать:

ValueError: int() base must be >= 2 and <= 36, or 0

Как выйти из данного положения?

P.S. Ктати, а разве бывает позиционная система счисления с основанием 0? Почему её Python разрешает?

Ответы

▲ 7Принят

Почему Python не работает с системами счисления, основания которых превышают 36?

Потому что Python не "знает" цифр больше 35. Первые десять берутся из обычной десятичной: 0...9, следующие 26 — буквы латиницы a...z. Так исторически сложилось ещё полвека назад. А какой символ по вашему он должен использовать для цифры 36?

Кcтати, а разве бывает позиционная система счисления с основанием 0? Почему её Python разрешает?

0 используется как специальное значение, означающее автоматическое определение основания системы счисления по формату строки. int("10", 0) == 10, int("0x10", 0) == 16, int("0b10", 0) == 2.

Если же основание системы счисления не указано, то считается равным 10.

Источник: https://docs.python.org/3/library/functions.html#int

▲ 3

Ошибка возникает, потому что в Python встроенная функция int() принимает второй аргумент только от 2 до 36. Чтобы работать с числами в системе счисления больше 36, можно воспользоваться библиотекой intlib.

from intlib import Int

n = 12345
base = 37
n_base_37 = Int(n).to_base(base)

Также в intlib есть метод from_base(), который можно использовать для перевода числа из другой системы счисления в 10-ую:

from intlib import Int

n_base_37 = "a1b2c3d4e5"
base = 37
n = Int(n_base_37, base=base)
▲ 1

Считайте значение в тридцатисимеричной системе руками. Функция из пяти строк:

import math


def is_prime(n):
    """Check if a number is prime."""
    return n >= 2 and all(n % i != 0 for i in range(2, math.isqrt(n) + 1))


def is_valid_in_base(n, base):
    """Check if a number is valid in given base."""
    return all(int(d) < base for d in str(n))


def value_in_base(n, base):
    v = 0
    for d in str(n):
        v = base * v + int(d)
    return v


base = 37
primes_base = []
for n in range(2, 4000):
    if is_valid_in_base(n, base) and is_prime(n) and is_prime(value_in_base(n, base)):
        primes_base.append(n)

print(primes_base)
$ py temp.py
[2, 3, 5, 7, 29, 41, 43, 61, 67, 113, 131, 137, 139, 179, 197, 227, 241, 263, 269, 283, 331, 397, 401, 463, 487, 599, 607, 641, 647, 683, 719, 733, 751, 797, 821, 863, 883, 1033, 1039, 1051, 1093, 1097, 1231, 1277, 1297, 1307, 1361, 1381, 1439, 1543, 1567, 1613, 1619, 1697, 1699, 1787, 1811, 1831, 1877, 1907, 1949, 1987, 2063, 2069, 2081, 2089, 2137, 2203, 2221, 2287, 2333, 2339, 2371, 2423, 2447, 2531, 2539, 2557, 2683, 2711, 2797, 2803, 2861, 2957, 2999, 3037, 3109, 3167, 3251, 3343, 3389, 3457, 3491, 3547, 3617, 3659, 3691, 3701, 3767, 3769, 3923, 3929, 3943]