In the previous two chapters of infinity multiplication for Groovy, I had demonstrated the methods and the programming code for multiplying two string of digits together at the rate of one digit at a time. If you need a reference on the method of multiplication, please refer to chapter one and two of infinity multiplication with the name “Infinity Multiplication – Beyond integer” and “Infinity Multiplication – Decimal, Precise Float Calculation”.

The methods of the previous two chapters are error proof, due to we are only processing one digit at a time. We were also storing the answer for each cycle of multiplication for the digit in the second value string on a separate temporary string before we join the temporary answer string to the final answer string. Nevertheless, the methods in the previous chapter could be inefficient for processing a large amount of data.

In this chapter, I will demonstrate what in my opinion consider the most optimized way for optimizing the previous chapters’ methods for the production environment. Same as the previous chapters, the source code was tested against hundred of thousand plus test cases. With this article, there is also the code for testing all the previous chapter source code and including this one. I also did a benchmark test for this production version of the source code of Infinity Multiplication versus the previous version of this program.

Previous Chapter: Decimal, Precise Float Calculation | Next Chapter: Beyond Memory |

#### Optimised The Code

Before discussing in regard to optimizing the code, I will discuss the benchmark score results from the benchmark test for this version of infinity multiplication. When testing for how fast the program executes, I produced two strings of number, each string contained forty digits in length. The strings are then passed into the function to execute 100,000 times, and the time it took to execute was recorded as the benchmark score. This test ran twice and the average result between the two tests is used as the final benchmark score.

This version of Infinity Multiplication for Groovy took 6.480 seconds to compute the results for 100,000 cases. For each case the same two strings of number were used, each string of number contained forty digits and did not contain the decimal. With the decimal, the program took 7.308 seconds to compute the results. To compare this to the previous version, the previous version took 127.252 seconds to compute the results for 100,000 cases without the decimal. For each case, the same two strings that tested this version of infinity multiplication were used. With the decimal, the previous version took 123.672 seconds to execute.

I know that the benchmark score can look funny from the single perspective of why when infiX dealing with the decimal, the program was computing faster for the previous version of infiX. This has something to do with how Groovy’s indexOf() string prototype function operate. On one hand, the infiX program will always inspect the string for a decimal doesn’t matter if the string contains a decimal or not. On the other hand, the indexOf() function will search through the input string for the decimal. When the indexOf() function found the decimal, the indexOf() function will exit and return the position for the decimal. When the string does not contain a decimal, the indexOf() function actually have to search through the entire string to look for the decimal.

How did I make the program run more than one hundred times faster? Instead of processing one digit at a time, I converted the program into processing nine digits at a time. I used the long int type for storing data between each calculation. For each multiplication cycle, the previous version would require to convert a string type digit to an integer type twice, convert the result to a string format, stores the result, calculate the leftover and the remainder. The previous version of infinity multiplication also produces a temporary answer string to computes the result for the final answer string.

By computing nine digits at a time, we would still use the same procedures for each multiplication cycle, however, the procedures are now applied to nine digits at a time for each multiplication cycle. Besides that, I removed the temporary answer string and directly produce the final result onto the final answer string. By removing the temporary answer string, I would also save memory usage and requires less memory to operate.

When choosing between the while and the for loop, I chose the while loop. For the formula of infiX in Groovy, the while loop was benchmarked to operate two times faster than the for loop. For joining the strings together, I chose the concat() function. The concat() function was benchmarked to operate faster than if I was to use the plus sign for concatenating two or more strings together. To get the digits from the strings, I used the substring() function instead of the “[]” bracket method. The “[]” bracket is more flexible in handling positions because the “[]” method can use a negative value for position and count the negative value as positions starting from the right side of the string. Nevertheless, the substring() function does operate faster. For getting one single character from a string, both the charAt() function and the “[]” bracket method were producing results at the same speed.

The reason why I only calculate nine digits at a time is due to the fact that the maximum value a 64 bits block long integer can hold is 9,223,372,036,854,775,807. Which in term is 19 digits in length. For a multiplication equation, nine digits multiply by another nine digits have the potential to produce the maximum value that is 18 digits in length. This is well below the maximum value that a 64 bits block integer can hold. If I was to compute 10 digits at a time I have the potential to produce a result with the maximum value of 99,999,999,980,000,000,001. This can overflow the memory of what a 64 bits block long integer can hold and produce an incorrect result.

To demonstrate an example of how to multiply more than one digits at a time, I used the formula for multiplying five digits at a time. The formula is easier to read when it is in the format of the five digits blocks. Nevertheless, this formula will persist through into more or fewer digits calculation per cycle.

Example: 92345 67890 x 12545 89085 92345 67890 x 12545 89085 -------------- Multiply 67890 to 89085 (80650) | leftover = 60479 and remainder = 0 Multiply 92345 to 89085 54325 | leftover = 82265 Add remainder and leftover +0 +60479 Value of this position (14804) | remainder = 1 Add remainder and leftover 1 +82265 Value of this position (82266) | 0 leftover and 0 remainder Current answer 82266 14804 80650 Multiply 67890 to 12545 80050 | leftover = 8516 Add current position value in answer string +14804 Value of this position (94854) | remainder = 0 Multiply 92345 to 12545 68025 | leftover = 15584 Add current position value in answer string +82266 Add remainder and leftover +8516 0 Value of this position (58807) | remainder = 1 Add remainder and leftover 1 +15584 Value of this position (15585) ---------------------------- Add the previous results together 15585 58807 94854 80650

With the formula above in context, it’s can be defined that we are multiplying all the digits in A string to B string in a block of five digits at a time. Each five block of digits in A string is multiplied by the first block of five digits in B. Each time we multiplied a block of five digits from A to the first block of five digits in B, we would only store a five digits block at a time to the answer string from right to left. Any values that are above five digits in length would be kept as the leftover for the next equation. When keeping the digits for storing into the answer string, the first five most digits from right to left would be kept. The sixth digits and beyond would be kept for leftover.

When we are adding the leftover to the result for the equation, if there are more than five digits value we would also keep the five first digits from the right and keep the left most digits as the remainder for our next equation.

After multiplying all the digits in A string to the first five block of digits in B string, we would then multiply all the digits in A string to the next block of five digits in B string. This time, however, our starting position for storing the value into the answer string would move over by five digits, starting from the right. This starting position would move over by another five when we are moving to the next block of five digits in B string, and so on.

When we are storing the result into the answer string, we would also have to add the result value to any value that the current position in the answer string hold. The same rule of remainder still applies to the equation.

With the above procedures in context and our program designed to work with nine digits at a time, the first variable we would need is how many digits we are calculating at a time. This value can extend the ability of the program. If the bit block for storing digits increase we can change this value to increase the amount of digit we are handling per equation. If we have to work in a restricted environment and the integer bits block is smaller, we can also change this value to adapt the program.

The second variable we would need is an index count of how many times we had read from B string. For this program, each time we read would translate to per nine digits block. The amount of how many digits we read can vary at the very end of the string. Nevertheless, this program was built to considers the variation in the final block of digits for both strings. This index variable was named posr.

Besides the index for reading, we would also need a variable for calculating which position we are working with in our answer string. The variable for calculating of where we are in the answer string is called posw. For converting our temporary multiplication result to a string type data before we write to the answer string, we produce the tempstr variable. For temporary holding the leftover value in a string type format, we created the leftoverstr variable.

byte digit = 9 long temp = 0 int alen = a.length() int blen = b.length() int bi = blen int posr = 0 int posw = 0 String output = "" String pad0 = "" String tempstr = "" String leftoverstr = "" while ( pad0.length() < digit - 1 ){ pad0 = "0" + pad0 }

For every time we are reading a position in B string, we would have to read all the position in A string. Thus the outer loop will read the digits in B string and jump by nine positions every execution, and for every outer loop execution, an inner loop will read all the position in A string and also jump by nine positions at a time.

To get nine digits from B string, I used the substring() string prototype function. The syntax of this function are, String.substring(argument_1) or String.substring(argument_1, argument_2). For the substring() function, argument one and two accepts integer value as input. The substring() function treats both arguments as positions within the string. The substring() function only accepts positive values for argument one and two. The substring() function counts positions from left to right of the string, and position zero being the first position in the string.

If only one argument was input, the substring() function will grab all the character at the defined position to the end of the string. If there was an input for the second argument, the substring() function will grab all the characters from the position that was defined by the first argument to the character that is one position before the position that was defined by the second argument. Thus if the string is length ten, the last position of the string would be position nine. If I wanted to grab the character in position nine, I would have to use position ten for the second argument. If argument one and argument two are the same position, the substring() function will return an empty string. If the positions to get the character from are out of range, the substring() function will produce an exception.

To get nine digits from B string, we can use the substring() function. For the first argument, we inputted into the substring() function, the value would be the current position of where we are at minus the amount of digit we wanted to work with. The value for the second argument would be the current position of where we are at in B string. Notice that we do not minus one of our string lengths to get the current position, this is due to Groovy’s substring() function will only get the digit that is just before the position that was defined by the second argument. Since in Groovy, string’s position start at zero, therefore the length of the string is actually one value higher than the last position of the string from left to right.

We also do not want the first argument value to turn into a negative. If the first argument value turned into a negative, the substring() function will produce an exception. Thus we declared a conditional statement to only accept the first argument’s value from the calculation if the value is not a negative. If the value is a negative value we would assign a zero value to the first argument. This is because the last block of digits on the left side of the string would most likely contain a varying amount of digits and would not have the exact amount of digits that we intended to work with. The method for grabbing a set of digits from A string is similar to the method of grabbing a set of digits from B string.

When we are executing the inner loop for calculation and when the answer string does contain an output value, we simply storing the answer into the output string bases on the procedures to this method. To get the leftover value, we would first convert the answer from the current multiplication cycle within the current block of digits into a string format. If the length of this temporary answer variable is larger than the amount of digit we intended the program to work with, we would get the digits that are more than the amount of digit we intended to work with from the left side of the string. Otherwise, we would assign a zero value for leftover in the event where the answer for the current multiplication cycle contain a value that when translating to digit lengthwise would have a length that is less than or equal to the amount of digit we intended to work with per multiplication cycle.

For the procedure of obtaining the leftover value, we can declare a conditional statement. If the statement is true we would utilize the substring() function on our tempstr which is the variable that currently holds the temporary answer for our current multiplication cycle in string format. For the first argument, we would input a zero value, which is the first position in the string. The second argument is the length of the tempstr minus the amount of digits we intended to work with per cycle.

When appending the result to the answer string, we want to always append the digits in the format that each block of digits contain the exact amount of digits we intended to work. Therefore we would have to append to the result zeroes in the event where the block of digits is less than the intended amount of digits we wanted to work. For the demonstration purpose, if we were to work with five digits and 1 00125 x 1 00001 was input into our program, The first five block of digits from A multiply by the first five block of digits in B would equal to 1 x 125 and the result would be 125. If we do not append zero to the beginning of the result to make up for the length, the next calculation will only add just a one to the beginning of this result in the answer string. Which in term is just 1125 instead of the correct answer which would be 1 00125.

To be able to always consistently produce a block of digits that match the amount of digit we intended to work with for all the result, we pad a string that contains one zero less than the amount of digits we intended to work with to the beginning of the result value. We then use the substring() function to grab the amount of digit that we wanted to worked with, which was nine for this version of infiX in Groovy from the right side of the string. For this procedure, we can input the tempstr variable’s length minus the amount of digit we intended to work with as the only argument for the substring() function. The substring() function will then grab all the digits from the defined position to the end of the string.

After we had multiply all the blocks of digits from A string to the first block of digits in B string and if there are any leftover values, we would assign this leftover value to the beginning of the answer string. We would still need the block to have a consistence amount of digit that was defined by the amount of digit we intended to work with at a time for this procedure.

This code block below demonstrate the mentioned procedures in Groovy.

while ( bi > 0 ){ int outlen = output.length() int ai = alen long z = Long.parseLong(b.substring((bi - digit > -1? bi - digit : 0), bi)) long leftover = 0 if ( outlen < 1 ){ while ( ai > 0){ temp = Long.parseLong(a.substring((ai - digit > -1? ai - digit: 0), ai)) * z + leftover tempstr = String.valueOf(temp) leftover = tempstr.length() > digit? Long.parseLong(tempstr.substring(0,tempstr.length() - digit)) : 0 tempstr = pad0.concat(tempstr) output = tempstr.substring(tempstr.length() - digit).concat(output) ai = ai - digit } if ( leftover > 0){ leftoverstr = pad0.concat(String.valueOf(leftover)) output = leftoverstr.substring(leftoverstr.length() - digit).concat(output) } }

The previous procedures are for when the answer string does not yet contain a value. However, it’s can get very complicated for when the answer string does contain a value. Each time we read a digit block in A string, we would have to calculate the position of where we are working with in our answer string. The starting position for the answer string is move over from the right to the left for each digit block we read in B string. Besides that, the position that we are working with in the answer string will also move over for each digits block we are currently reading from in A string.

To calculate this position, first we get the starting position by multiply how many times we had read from B string to the amount of digit we wanted to work with. Second, we multiply the amount of times we had read from A string to the amount of digits we wanted to work with and add this value to the first value. In a short procedure, we can describe it as how many times we read from B string plus how many times we read from A string and multiply the value to the amount of digits we intended to work with.

For this time of multiplying a digits block from A string to the digits block in B string, we have to add the result value to the value of the digits block of the current position we are working with in the answer string. The result from this addition procedure will be store in a temporary variable name tempadd.

To get the digits in the answer string, we use the answer string length minus the current position that we are working with minus the amount of digit we intended to work with as the first argument for our substring() function. If the position turned into a negative value, we simply assign a zero value to the argument. For the second argument value, we would pass the answer string’s length minus the position we are working with to the substring() function. If the second argument value turned into a negative we would also assign a zero value in place for the negative value as the second argument. The reason of why these value can be negative is because we would eventually work on a position that is beyond the first position in the answer string.

The digits we got from the answer string would be stored in a variable name outposstr. We would then convert the outposstr to a long type since we are working with a long integer or a 64 bits block integer. The value from this conversion would be stored in a variable name outposval. Nevertheless, if we were working in a position where the answer string does not yet contain a value, outposstr would not get any value back from the substring function() and would be empty. Thus we would check if outposstr is empty with the isEmpty() function. If outposstr does not have a value we would assign a zero value to outposval, otherwise, we would convert outposstr using the parseLong() function.

We would also produce a remainder value from our addition operation if there is any. The procedure for producing a remainder is same as producing the leftover value for the multiplication procedure.

After producing the tempadd variable we would then store this variable into our answer string by getting all the digits from the beginning of the answer string to where we grabbed the first digit from the answer string. If the calculation to get this position value produced a negative value, we have to turn this value to a zero value. This will happen when we are working to the leftmost of the answer string and the answer string does not yet contain a value. When both of the substring() function’s arguments are zero in value, an empty string would be returned as the value. Thus we do not have to worry about if the position does not contain a value in this scenario. We then add our tempaddstr value to the right side of this string and then add the rest the digits from after the last digit we just grabbed from the answer string for the addition procedure to the end of the answer string.

After multiplying all the digits in A string to the set of digits in B string, we would add any remainder and leftover to the leftmost side of our answer string. The below code block demonstrate the above procedures into programming statements for Groovy.

long tempadd = 0 long outposval = 0 int remainder = 0 int loopidx = 0 String tempaddstr = "" String outposstr = "" while ( ai > 0){ posw = (posr + loopidx) * digit temp = Long.parseLong(a.substring((ai - digit > -1? ai - digit: 0), ai)) * z + leftover + remainder tempstr = String.valueOf(temp) leftover = tempstr.length() > digit? Long.parseLong(tempstr.substring(0,tempstr.length() - digit)) : 0 tempstr = pad0.concat(tempstr) outlen = output.length() outposstr = output.substring((outlen - posw - digit > 0 ? outlen - posw - digit : 0), (outlen - posw > 0 ? outlen - posw : 0)) outposval = outposstr.isEmpty()? 0 : Long.parseLong(outposstr) tempadd = Long.parseLong(tempstr.substring(tempstr.length() - digit )) + outposval tempaddstr = String.valueOf(tempadd) remainder = tempaddstr.length() > digit? 1 : 0 tempaddstr = pad0.concat(String.valueOf(tempadd)) output = output.substring(0, (outlen - posw - digit > 0? outlen - posw - digit : 0)).concat(tempaddstr.substring(tempaddstr.length() - digit)).concat(output.substring((outlen - posw > 0? outlen - posw : 0), outlen)) loopidx = loopidx + 1 ai = ai - digit } if ( leftover + remainder > 0){ leftoverstr = pad0.concat(String.valueOf(leftover + remainder)) output = leftoverstr.substring(leftoverstr.length() - digit).concat(output) }

As for the testing to see if this function work. This code block below is what I used to test the previous version of InfiX function against the native multiplication function of the Groovy’s platform. For the previous version, since we are calculating one digit at a time, the correct result for calculating values that within the boundary of what an integer can hold will persist through into the longer string of digits. I also tested the library against Ruby’s native multiplication function. As it seems, Ruby’s native multiplication function can also calculate a very large amount of digits.

When testing for a decimal value, take consideration that the native calculates function will not be able to provide the actual precise decimal calculation. This tester will tell you, how many cases did not match and will also tell you the answer for the native function on the left and infiX answer on the right. If you use a calculator or manual calculation, you will be able to distinguish the pattern of the result between infiX and the native multiplication function.

To use this tester, simply look for version two of infiX which is called “Decimal, Precise Float Calculation” and place the tester code into main(). This code below is the tester cases. I preset the amount of run to 5000 cases, this could be increased. For Groovy, it is safe to set the amount of case to run at less than or equal to 100,000 cases at a time. Otherwise, it might take sometimes to get back the result. This code block below is the tester for the version two of infiX.

int um = 0 int m = 0 for (int id = 0; id < 1; id++){ int a = (int)(Math.random() * (99 - 0) + 0) int ac = (int)Math.floor(Math.random() * (9 - 1) + 1) int b = (int)(Math.random() * (99 - 1) + 1 ) int bc = (int)(Math.random() * (9 - 1) + 1) String padA = ""; String padB = ""; for (int idn = 0; idn < (int)(Math.random() * (3 - 0) + 0); idn++){ padA = "0" + padA } for (int idn = 0; idn < (int)(Math.random() * (3 - 0) + 0); idn++){ padB = "0" + padB } String ta = "-" + String.valueOf(a) + "." + padA + String.valueOf(ac) String tb = "-" + String.valueOf(b) + "." + padB + String.valueOf(bc) float test1 = Float.parseFloat(ta) * Float.parseFloat(tb) String test2 = libZ.infiX(ta, tb ) if ( !(String.valueOf(test1).equals(test2)) ) { um = um + 1 System.out.println("Question: " + ta + " * " + tb) System.out.println("Native Multiplication: " + String.valueOf(test1) + " | infiX: " + test2 + "\n") } if (String.valueOf(test1).equals(test2)){ m = m + 1 } } System.out.format("Matched: %d cases. \nUnmatched : %d cases.", m,um)

For testing this version of infiX, I tested this version of infiX versus the previous version of infiX. Since the previous version already thoroughly tested, this one will produce the correct answer if the answer matches with the previous one. The previous version does take a long time to produce mass results. However, as the prototype, I built the previous version as a demonstrator to the articles I wrote and also a tester to test the future release versions of the infiX program.

To use the tester below, simply have this version of infiX and the version two of infiX in the same script file with the tester. Rename one of the infiX function if necessary. This tester will produce five blocks of random numbers in front of the decimal for each string. The random blocks of numbers can be anywhere between one or five digits. The tester will then pad 0 to 15 zeroes behind the decimal and then three blocks of random numbers before adding another 0 to 15 zeroes and then the last two blocks of random digits. As recommended, this tester should not be set to execute above 100000 cases at a time. It can take a long time to produce the results since the previous version of InfiX does take a long time to produce an answer.

The below code block is the tester code for Groovy.

int um = 0 int m = 0 for (int id = 0; id < 50000; id++){ String a1 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String a2 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String a3 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String a4 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String a5 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String ac1 = String.valueOf((int)(Math.random() * (9999 - 1) + 1)) String ac2 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String ac3 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String ac4 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String ac5 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String b1 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String b2 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String b3 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String b4 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String b5 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String bc1 = String.valueOf((int)(Math.random() * (9999 - 1) + 1)) String bc2 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String bc3 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String bc4 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String bc5 = String.valueOf((int)(Math.random() * (9999 - 0) + 0)) String padA1 = "" String padA2 = "" String padB1 = "" String padB2 = "" for (byte idn = 0; idn < (byte)(Math.random() * (15 - 0) + 0); idn++){ padA1 = "0" + padA1 } for (byte idn = 0; idn < (byte)(Math.random() * (15 - 0) + 0); idn++){ padA2 = "0" + padA2 } for (byte idn = 0; idn < (byte)(Math.random() * (15 - 0) + 0); idn++){ padB1 = "0" + padB1 } for (byte idn = 0; idn < (byte)(Math.random() * (15 - 0) + 0); idn++){ padB2 = "0" + padB2 } String ta = "-" + a1 + a2 + a3 + a4 + a5 + "." + padA1 + ac1 + ac2 + ac3 + padA2 + ac4 + ac5 String tb = "+" + b1 + b2 + b3 + b4 + b5 + "." + padB1 + bc1 + bc2 + bc3 + padB2 + bc4 + bc5 String test1 = libZ.infiX(ta, tb) String test2 = libZ.infiX2(ta, tb) System.out.format("Cases #%d: %s * %s \n", id, ta, tb) if ( !(String.valueOf(test1).equals(test2)) ) { um = um + 1 System.out.println("Unmatch cases #" + String.valueOf(um)) System.out.println("Question: " + ta + " * " + tb) System.out.println("infiX3: " + String.valueOf(test1) + " | infiX2: " + test2 + "\n") } if (String.valueOf(test1).equals(test2)){ m = m + 1 } } System.out.println("") System.out.format("Matched: %d cases. \nUnmatched : %d cases.", m,um)

The below code snippet is the full function for this tutorial. If you like this article or the infiX program, please share the link to this article on any of the social network platform. If you have any comments please feel free to give a comment down below. Any suggestions to make this program better are welcome.

**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 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 normal usage version of infinity multiplication written for the Groovy Programming Language and is designed for a production environmen. // The first limitation of this version is how much memory the Groovy Programming Language allow the string to be store. // The second limitation is how much memory Groovy's environment can assign to the program. // If memory allow, for this version a string can only be less than 1,073,741,823 digits // // Example of memory usage calculation: // 500 megabyte string of digits multiply to another 500 megabyte string of digits. // 1000 Mb of memory to store the strings outside of the function. // 1000 Mb of memory for when the strings are passing into the function. // 1000 Mb for the answer string. // 100 Mb (this can vary but most likely to be less than this) for script operation. // 3100 Mb of memory is requires for adding two strings of digits that cost 500MB per string. public class libZ { public static String infiX(String a, String b) { boolean isaNeg = a[0] == '-' boolean isbNeg = b[0] == '-' a = a.replaceAll('^[-+]+', "") b = b.replaceAll('^[-+]+', "") a = a.replaceAll('^0+', "") b = b.replaceAll('^0+', "") int aDecPos = a.indexOf('.') int bDecPos = b.indexOf('.') int oDecPos = 0 if ( aDecPos > -1){ a = a.replaceAll('0+$', "") aDecPos = ((a.length() - 1 - aDecPos) > 0)? (a.length() - 1 - aDecPos) : 0 a = a.replaceAll('[.]', "") } if ( bDecPos > -1){ b = b.replaceAll('0+$', "") bDecPos = ((b.length() - 1 - bDecPos) > 0)? (b.length() - 1 - bDecPos) : 0 b = b.replaceAll('[.]', "") } if ( (a.length() < 1 || b.length() < 1 ) ){ return "0" } if ( a.equals('1') && aDecPos < 1 ){ if ( bDecPos > 0 ){ b = b.substring(0, b.length() - bDecPos).concat(".").concat(b.substring(b.length() - bDecPos)) b = b.charAt(0) == '.'? "0".concat(b): b return ((isaNeg != isbNeg)? "-".concat(b) : b) } return ((isaNeg != isbNeg)? "-".concat(b) : b) } if ( b.equals('1') && bDecPos < 1 ){ if ( aDecPos > 0 ){ a = a.substring(0, a.length() - aDecPos).concat(".").concat(a.substring(a.length() - aDecPos)) a = a.charAt(0) == '.'? "0".concat(a): a return ((isaNeg != isbNeg)? "-".concat(a) : a) } return ((isaNeg != isbNeg)? "-".concat(a) : a) } if ( aDecPos > -1 || bDecPos > -1 ){ aDecPos = (aDecPos > -1)? aDecPos : 0 bDecPos = (bDecPos > -1)? bDecPos : 0 oDecPos = aDecPos + bDecPos } byte digit = 9 long temp = 0 int alen = a.length() int blen = b.length() int bi = blen int posr = 0 int posw = 0 String output = "" String pad0 = "" String tempstr = "" String leftoverstr = "" while ( pad0.length() < digit - 1 ){ pad0 = "0" + pad0 } while ( bi > 0 ){ int outlen = output.length() int ai = alen long z = Long.parseLong(b.substring((bi - digit > -1? bi - digit : 0), bi)) long leftover = 0 if ( outlen < 1 ){ while ( ai > 0){ temp = Long.parseLong(a.substring((ai - digit > -1? ai - digit: 0), ai)) * z + leftover tempstr = String.valueOf(temp) leftover = tempstr.length() > digit? Long.parseLong(tempstr.substring(0,tempstr.length() - digit)) : 0 tempstr = pad0.concat(tempstr) output = tempstr.substring(tempstr.length() - digit).concat(output) ai = ai - digit } if ( leftover > 0){ leftoverstr = pad0.concat(String.valueOf(leftover)) output = leftoverstr.substring(leftoverstr.length() - digit).concat(output) } } else { long tempadd = 0 long outposval = 0 int remainder = 0 int loopidx = 0 String tempaddstr = "" String outposstr = "" while ( ai > 0){ posw = (posr + loopidx) * digit temp = Long.parseLong(a.substring((ai - digit > -1? ai - digit: 0), ai)) * z + leftover + remainder tempstr = String.valueOf(temp) leftover = tempstr.length() > digit? Long.parseLong(tempstr.substring(0,tempstr.length() - digit)) : 0 tempstr = pad0.concat(tempstr) outlen = output.length() outposstr = output.substring((outlen - posw - digit > 0 ? outlen - posw - digit : 0), (outlen - posw > 0 ? outlen - posw : 0)) outposval = outposstr.isEmpty()? 0 : Long.parseLong(outposstr) tempadd = Long.parseLong(tempstr.substring(tempstr.length() - digit )) + outposval tempaddstr = String.valueOf(tempadd) remainder = tempaddstr.length() > digit? 1 : 0 tempaddstr = pad0.concat(String.valueOf(tempadd)) output = output.substring(0, (outlen - posw - digit > 0? outlen - posw - digit : 0)).concat(tempaddstr.substring(tempaddstr.length() - digit)).concat(output.substring((outlen - posw > 0? outlen - posw : 0), outlen)) loopidx = loopidx + 1 ai = ai - digit } if ( leftover + remainder > 0){ leftoverstr = pad0.concat(String.valueOf(leftover + remainder)) output = leftoverstr.substring(leftoverstr.length() - digit).concat(output) } } posr = posr + 1 bi = bi - digit } if ( oDecPos > 0 ){ while (output.length() < oDecPos){ output = "0".concat(output) } output = output.substring(0, output.length() - oDecPos).concat(".").concat(output.substring(output.length() - oDecPos)) output = output.replaceAll('0+$', "") output = output[-1].equals('.')? output[0..-2] : output output = output.replaceAll('^0+', "") output = output[0].equals('.') ? "0".concat(output) : output return (isaNeg != isbNeg? "-".concat(output): output) } output = output.replaceAll('^0+', "") return (isaNeg != isbNeg? "-".concat(output): output) } } String x = ".9999999999999999999999999999999" String y = ".9999999999999999999999999999999" c = libZ.infiX(x,y) println(c)

This post was written by Kevin and was first post @ http://kevinhng86.iblog.website.

Original Post Name: "Working With Number – Infinity Multiplication – Optimised The Code – Groovy".

Original Post Link: https://kevinhng86.iblog.website/2017/02/24/working-with-number-infinity-multiplication-optimised-the-code-groovy/.

**Advertisement**