Однако при запуске программы и вводе 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))
Я обнаружил, что показатель степени вычисляется довольно быстро (даже если он имеет сотни миллионов цифр) и не требует много памяти, а трудности с большими входными данными почти полностью возникают на этапе вычисления mp.log10(nums[0]).
Обратите внимание, что у меня есть gmpy2 установлен для более быстрых вычислений с чрезвычайно высокой точностью.
Это проблема только IDLE? (Я видел, что Python использует больше памяти, чем в VSCode, и это не вызывает никаких проблем).
Я хотел бы знать, есть ли обходной путь для этой проблемы, чтобы можно было вычислить первые цифры, когда экспонента имеет более 200 миллионов цифр (именно тогда проблема, вероятно, начинает возникать).