Python Function – Infinity Multiplication – Beyond Memory

Advertisement

# "Copyright Notice", please do not remove.
# Written by Kevin Ng
# The full tutorial on this subject can be found @ http://kevinhng86.iblog.website or http://programming.world.edu.
# Release date to http://programming.world.edu will lag at least one week after release on http://kevinhng86.iblog.website
# This source code file is a part of Kevin Ng's Z library.
# This source code is licenses under CCDL-1.0  A copy of CDDL1.0 can be found at https://opensource.org/licenses/CDDL-1.0
# End "Copyright Notice"

# Notice: This is the protype version of infiXF.
#         This version does support decimal calculation.
#         InfiXF is for sciencetific use.

# Limitation: Although had not calculate the number to be that large yet, in theory InfiXF can calculate two strings of digits that are 1/5 the size of the hard drive.
#             If the hard drive is 1 Terabyte, This program can calculate the multiplication procedure for two strings of digit with the combine storage of 200 GB.
#             That is about 100 billion digits in length for each string of digits.
#             This version does not come with the renderer.
#             After a huge calculation, and if the answer file is larger than 1GB another program woulb be requires to render the answer on screen.
#             InfiXF does not consume memory and have very little memory foot print.
#             InfiXF however does requires the storage space as large as the two files that contained the strings of digits to produce the answer string.
#             100 * 100 GB would requires 400 GB for storing the temporary files and 400 Gb for the result file.

class libZ:
    def infiXF(self):
        import os
        afile = "a.infiX"
        bfile = "b.infiX"
        atmp = afile + ".tmp"
        btmp = bfile + ".tmp"
        outputfile = "result.infiX"
        outputtmp = outputfile + ".tmp"
        dAfterDecA = -1
        dAfterDecB = -1
        dAfterDecT = 0
        perReadTmp = 50 # This is changeable, how many character to read at once during temporary file reading.
        tmpDReadA = 0
        tmpDReadB = 0
        readA = ""
        readB = ""

        # Start processing file A
        FileA = open(afile, "r")

        readA = FileA.read(1)
        isaNeg = readA == "-"

        TmpA = open(atmp, "w")
        FileA.seek(0, 0)
        readA = FileA.read(perReadTmp)
        readA = readA.lstrip("+-")
        readA = readA.rstrip()

        dAfterDecA = readA.find(".")
        dAfterDecA = (len(readA) - 1 - dAfterDecA) if dAfterDecA > -1 else dAfterDecA
        if (dAfterDecA > -1):
            readA = str.replace(readA, ".", "")
        TmpA.write(readA)

        while True:
            readA = FileA.read(perReadTmp)
            readA = readA.rstrip()
            if (dAfterDecA < 0):
                dAfterDecA = readA.find(".")
                dAfterDecA = (len(readA) - 1 - dAfterDecA) if dAfterDecA > -1 else -1
                if (dAfterDecA > -1):
                    readA = str.replace(readA, ".", "")
            else:
                tmpDReadA = len(readA)
                dAfterDecA = dAfterDecA + tmpDReadA
            TmpA.write(readA)
            if not readA:
                break
        TmpA.close()
        FileA.close()
        # End processing file A

        # Start processing file B
        FileB = open(bfile, "r")

        readB = FileB.read(1)
        isbNeg = readB == "-"

        TmpB = open(btmp, "w")
        FileB.seek(0, 0)
        readB = FileB.read(perReadTmp)
        readB = readB.lstrip("+-")
        readB = readB.rstrip()

        dAfterDecB = readB.find(".")
        dAfterDecB = (len(readB) - 1 - dAfterDecB) if dAfterDecB > -1 else dAfterDecB
        if (dAfterDecB > -1):
            readB = str.replace(readB, ".", "")
        TmpB.write(readB)
        while True:
            readB = FileB.read(perReadTmp)
            readB = readB.rstrip()
            if (dAfterDecB < 0):
                dAfterDecB = readB.find(".")
                readB = readB.rstrip()
                dAfterDecB = (len(readB) - 1 - dAfterDecB) if dAfterDecB > -1 else -1
                if (dAfterDecB > -1):
                    readB = str.replace(readB, ".", "")
            else:
                tmpDReadB = len(readB)
                dAfterDecB = dAfterDecB + tmpDReadB
            TmpB.write(readB)
            if not readB:
                break
        TmpB.close()
        FileB.close()
        # End processing file B

        dAfterDecA = 0 if dAfterDecA < 0 else dAfterDecA
        dAfterDecB = 0 if dAfterDecB < 0 else dAfterDecB
        dAfterDecT = dAfterDecA + dAfterDecB
        atmpsize = os.path.getsize(atmp)
        btmpsize = os.path.getsize(btmp)
        digit = 9; # This is the amount of digits to calculate per cycle.
        digitneg = digit * -1
        pad0 = ""

        while (len(pad0) < (digit - 1)):
            pad0 = "0" + pad0

        OutputTmp = open(outputtmp, "w")
        idn = 0
        premakeoutlen = (atmpsize + btmpsize) + (digit * 2)
        while (idn < premakeoutlen):
            OutputTmp.write(pad0 if len(pad0) > 0 else "0")
            idn = idn + (1 if (digit - 1 == 0) else digit - 1)
        OutputTmp.close()

        a = 0
        b = 0
        o = 0
        posrB = 1
        posrO = 1
        loopidxB = 1
        temp = 0
        tempadd = 0
        blen = btmpsize
        olen = os.path.getsize(outputtmp)

        # Start calculation code

        TmpB = open(btmp, "r")
        while (posrB != 0):
            alen = atmpsize
            posrA = 1
            leftover = 0
            remainder = 0
            loopidxA = 1
            posrB = blen - (loopidxB * digit)

            TmpB.seek((posrB if posrB > 0 else 0), 0)
            b = TmpB.read((digit if posrB > 0 else digit + posrB))

            TmpA = open(atmp, "r")
            OutputTmp = open(outputtmp, "r+")
            while (posrA != 0):
                posrO = olen - ((loopidxA + loopidxB - 1) * digit)
                posrA = alen - (loopidxA * digit)

                TmpA.seek((posrA if posrA > 0 else 0), 0)
                a = TmpA.read((digit if posrA > 0 else digit + posrA))

                temp = str(int(b) * int(a) + remainder + leftover)
                leftover = int(temp[0:digitneg] or "0")

                OutputTmp.seek(posrO, 0)
                o = OutputTmp.read(digit)

                tempadd = str(int(temp[digitneg:]) + int(o))
                remainder = int(tempadd[0:digitneg] or "0")

                OutputTmp.seek(posrO, 0)
                OutputTmp.write((pad0 + tempadd[digitneg:])[digitneg:])
                posrA = posrA if posrA > 0 else 0
                loopidxA = loopidxA + 1

            if (remainder + leftover > 0):
                posrO = posrO - digit
                OutputTmp.seek(posrO, 0)
                OutputTmp.write((pad0 + str(leftover + remainder))[digitneg:])
            OutputTmp.close()
            TmpA.close()
            posrB = posrB if posrB > 0 else 0
            loopidxB = loopidxB + 1
        TmpB.close()
        # End calculation code

        dBeforeDec = olen - dAfterDecT
        lead0End = 0
        posw = 0
        readOutputTmp = ""
        checker = ""
        truncatediff = 0
        truncatelen = 0
        truncatestr = ""

        # Start processing result
        OutputTmp = open(outputtmp, "r")
        Output = open(outputfile, "w")

        if (isaNeg != isbNeg):
            Output.write("-")
        while (posw < dBeforeDec):
            OutputTmp.seek(posw, 0)
            readOutputTmp = OutputTmp.read((perReadTmp if posw + perReadTmp < dBeforeDec else dBeforeDec - posw))
            if (lead0End == 0):
                readOutputTmp = readOutputTmp.lstrip("0")
                lead0End = 1 if len(readOutputTmp) > 0 else 0
            Output.write(readOutputTmp)
            posw = posw + perReadTmp if posw + perReadTmp < dBeforeDec else dBeforeDec
        Output.close()
        # End processing digits before the decimal

        outputlen = os.path.getsize(outputfile)
        Output = open(outputfile, "a+")
        if (outputlen < 2):
            Output.seek(0,0)
            checker = Output.read(1)
            if (len(checker) < 1 or checker is "-"):
                Output.write("0")

        Output.seek(outputlen,0)
        if (dAfterDecT > 0):
            Output.write(".")

        # Start processing digits after the decimal
        while (posw < olen):
            OutputTmp.seek(posw, 0)
            readOutputTmp = OutputTmp.read(perReadTmp)
            truncatestr = readOutputTmp
            truncatestr = readOutputTmp.rstrip("0")
            truncatediff = len(readOutputTmp) - len(truncatestr)
            truncatelen = truncatediff + truncatelen if truncatediff == len(readOutputTmp) else truncatediff
            Output.write(readOutputTmp)
            posw = posw + perReadTmp

        Output.close()
        OutputTmp.close()
        # End processing digits after the decimal

        # Start truncating trailing zeroes after the decimal if there is any
        outputlen = os.path.getsize(outputfile)

        Output = open(outputfile, "r+")
        Output.truncate(outputlen - truncatelen)
        Output.close()

        outputlen = os.path.getsize(outputfile)

        Output = open(outputfile, "a+")
        Output.seek(outputlen - 1, 0)
        readOutputTmp = Output.read(1)
        if (readOutputTmp is "."):
            Output.seek(outputlen - 1, 0)
            Output.truncate(outputlen - 1)
        Output.close()
        # End truncating zeroes

    def fileRand(self):
        import random
        randDigitA = random.randint(0, 350) + 40
        randDigitB = random.randint(0, 350) + 40

        randDecPOSA = random.randint(0, randDigitA - 20) + 20
        randDecPOSB = random.randint(0, randDigitB - 20) + 20

        RANDOMA = open("a.infiX", "w")
        RANDOMA.write("-")
        for idn in range(0, randDigitA):
            RANDOMA.write(str(random.randint(0, 9)))
            if (idn == randDecPOSA):
                RANDOMA.write(".")
        RANDOMA.close()

        RANDOMB = open("b.infiX", "w")
        for idn in range(0, randDigitB):
            RANDOMB.write(str(random.randint(0, 9)))
            if (idn == randDecPOSB):
                RANDOMB.write(".")
        RANDOMB.close()

e = libZ()
e.fileRand()
e.infiXF()

print("Check in the current directory.\n a.infiX is the file that hold the first set of digits.\n b.infiX is the second file that hold the digits.\n result.infiX is the result of the multiplication procedure.\n")
print("The name of the temporary file for them are a.infiX.tmp, b.infiX.tmp, result.infiX.tmp.\n")
print("Temporary files can be delete after execution, but are currently kept for debuging purposes.")
Advertisement
directory-software-online-bussiness-script


Random Article You May Like