Недавно я написал программу на Python для вычисления первой и последней цифр чрезвычайно больших чисел и обнаружил, что код для вычисления первых цифр работает хорошо даже для входных данных, где показатель степени имеет более 100 000 000 цифр.
Однако при запуске программы и вводе 2^2^10^9, где показатель степени представляет собой число из 301 миллиона цифр, любое желаемое количество цифры (я обычно ставлю 100 при тестировании программы) и «Да» после предупреждающего сообщения, программа завершает расчет в середине, а IDLE перезапускает оболочку без появления какого-либо сообщения об ошибке. Это означает, что скорее всего произошел сбой интерпретатора Python. Я попробовал выполнить вычисления еще раз, чтобы проверить, не случайность ли это, но проблема возникла снова примерно в том же месте вычислений.
Код приведен ниже:
import mpmath as mp
def report_too_big_for_first_digits(): #Validation function for first digit calculation
raise ValueError("Result is too large to calculate first digits")
nums = input().split("^")
desired_digits = int(input())
try:
nums = nums[:nums.index("1")]
except ValueError:
pass
try:
nums = nums[:nums.index("0")-1]
except ValueError:
pass
nums = [int(n) for n in nums]
first_digits = 0
try:
log_exp = 0
exponent = 1
required_digits = 0
if len(nums) >= 7 or (len(nums) == 6 and (nums[3] > 2 or nums[4] > 2 or nums[5] > 2)):
report_too_big_for_first_digits()
for i in range(1, len(nums)):
if i == len(nums)-1:
log_exp = exponent*mp.log10(nums[1])
required_digits = int(log_exp) + desired_digits + 5
if required_digits > 5000000000:
report_too_big_for_first_digits()
elif required_digits > 100000000:
print(f"Warning: Calculating the first digits requires {required_digits} digits of accuracy. This will require a large amount of memory and may cause the code to fail, or the Python interpreter to crash. The calculation may also take a long time to complete.")
print("Do you wish to continue the calculation?")
confirmation = input()
if confirmation != "Yes":
raise ValueError("The calculation of the first digits was cancelled") #Here we use ValueError as a control flow mechanism for cancelling the calculation, even though this isn't really an "error" by the spirit of the law
mp.mp.dps = required_digits
exponent = mp.power(nums[-1*i], exponent)
print("Exponent calculated!")
log_b = mp.log10(nums[0])
print("Logarithm calculated!")
log_result = log_b*exponent
print("Multiplication complete!")
log_result = mp.frac(log_result)
mp.mp.dps = desired_digits + 5
first_digits = mp.power(10, log_result)
except MemoryError:
print("Not enough memory")
except ValueError as e:
print(e)
#Compute the last digits.
result = 1
#FIXME: Last digits of a^b when b mod 10^desired_digits is small and a is not coprime to 10
for i in range(1, len(nums)+1):
result = pow(int(nums[-1*i]), result, 10**desired_digits)
if result == 0 or result == 1:
result += 10**desired_digits
last_digits = result
if first_digits == 0:
print("............", last_digits)
else:
print(str(first_digits).replace(".","")[:desired_digits], "............", last_digits)
with open("output.txt", "r+") as output_file:
output_file.write(str(first_digits).replace(".",""))
output_file.write("............")
output_file.write(str(last_digits))
Сбой постоянно происходит, когда использование памяти достигает определенного порога; Максимальное использование памяти процессом Python, который я видел в диспетчере задач незадолго до сбоя, составляло около 3800 МБ. На тот момент на моем компьютере все еще было около 22 гигабайт свободной памяти, и, основываясь на меньших вычислениях, я подсчитал, что на это ушло бы чуть меньше шести гигабайт. (Я обязательно закрываю все другие программы, прежде чем приступать к каким-либо большим вычислениям, за исключением диспетчера задач для мониторинга использования ресурсов).
Я обнаружил, что показатель степени вычисляется довольно быстро (даже если он имеет сотни миллионов цифр) и не требует много памяти, а трудности с большими входными данными почти полностью возникают на этапе вычисления mp.log10(nums[0]).
Обратите внимание, что у меня есть gmpy2 установлен для более быстрых вычислений с чрезвычайно высокой точностью.
Это проблема только IDLE? (Я видел, что Python использует больше памяти, чем в VSCode, и это не вызывает никаких проблем).
Я хотел бы знать, есть ли обходной путь для этой проблемы, чтобы можно было вычислить первые цифры, когда экспонента имеет более 200 миллионов цифр (именно тогда проблема, вероятно, начинает возникать).
Я обнаружил, что Windows создала следующий отчет о проблеме, предполагая, что проблема связана с переполнением буфера:
Source
Python
Summary
Stopped working
Date
4/14/2026 12:58 PM
Status
Report sent
Description
Faulting Application Path: C:\Program Files\WindowsApps\PythonSoftwareFoundation.Python.3.13_3.13.3312.0_x64__qbz5n2kfra8p0\pythonw3.13.exe
Problem signature
Problem Event Name: MoBEX
Package Full Name: PythonSoftwareFoundation.Python.3.13_3.13.3312.0_x64__qbz5n2kfra8p0
Application Name: praid:PythonW
Application Version: 3.13.12150.1013
Application Timestamp: 69823dca
Fault Module Name: ucrtbase.dll
Fault Module Version: 10.0.26100.7623
Fault Module Timestamp: 53a0792e
Exception Offset: 00000000000a4ace
Exception Code: c0000409
Exception Data: 0000000000000007
OS Version: 10.0.26200.2.0.0.768.101
Locale ID: 1033
Additional Information 1: dce9
Additional Information 2: dce9ef7b55b80a676be60f8e511368da
Additional Information 3: 4562
Additional Information 4: 45629b425082427e350bde9617397a8c
Extra information about the problem
Bucket ID: 9d376031b76bbcbaea08e000e939a296 (1875995539317301910)