ARTICLE AD BOX
I have recently written a Python program to calculate the first and last digits of extremely large numbers, and have found that the code for calculating the first digits works well even for inputs where the exponent has over 100,000,000 digits.
However, when running the program and inputting 2^2^10^9, where the exponent is a 301 million-digit number, any number of desired digits (I usually put 100 when testing the program), and "Yes" after the warning message, the program terminates mid-calculation and IDLE restarts the shell without any error message appearing. This means that the Python interpreter most likely crashed. I tried the computation again to see if it was a fluke, but the problem occurred again at around the same point in the computation.
Code is below:
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))The "crash" consistently occurs when the memory usage reaches a certain threshold; the highest memory usage by the Python process I saw in Task Manager just before the crash was around 3800 MB. My computer still had around 22 gigabytes of free memory at that point, and based on smaller computations I estimate that this would have taken just under six gigabytes. (I make sure to close all other programs before attempting any large computations, except for Task Manager to monitor resource usage).
I found that the exponent gets calculated fairly quickly (even when it has hundreds of millions of digits) and doesn't require a lot of memory, and the difficulty with large inputs comes almost entirely from the step of calculating mp.log10(nums[0]).
Note that I have gmpy2 installed for faster calculations with extremely high precision.
Is this just an issue with IDLE? (I have seen Python using more memory than that in VSCode without causing any issues).
I'd like to know if there is a workaround to this issue so that calculating the first digits when the exponent has more than about 200 million digits (which is when the issue likely starts to occur) can be achieved.
