# R – Infinity Multiplication – Decimal, Precise Float Calculation

In the previous chapter of infinity multiplication, we were discussing in regard to storing two integer numbers in string format and how to apply mathematical multiplication formula on the two strings by multiplying one digit at a time to produce an answer.

When it’s come to applying a mathematical formula on numbers that contains decimal values, since computer stores integer binary value as a whole digit and their base increase by the power of two for every additional binary digit, it is not possible to inject a decimal into a correct binary position. Thus computer software will usually utilize a floating point calculation formula on numbers which contains decimal values. Numbers with decimal values are stored as a float type in the computer. Thus numbers with decimal values usually describe as a float when it’s related to programming or computer.

Float calculation formula can be very precise on certain values. Nevertheless, there are values which float calculation have to round off some of the digits on the right side of the decimal to get a near precision value. These type of rounding can have minor affection in our daily life and likely to not affect our day to day mathematical calculation.

Nevertheless, if we truly want to calculate a decimal value that can be thousand of digits long, is there a solution to that? This is the second chapter of “Infinity Multiplication”, “Decimal, Precise Float Calculation”.

To have a little hint on this infinity subject, most of my readers ask me if this is truly an infinity library and is this truly an infinity subject? Infinity is the subject that is very hard to explain in words. Since the values can be endless and since it is endless, can we really calculate it? **This is my formula for calculating an infinity value “infC = infA = infAL” or can be represent with “C = A = AL”, which can also translate to “Infinity Calculation equal to Infinity Assumption and is equal to Infinity Alteration”**. I will discuss in regard to the infinity formula and how to apply the formula in a programming perspective in chapter five of the infinity multiplication, division, adding and subtracting subject. Chapter five of the infinity subject will only be available in full at http://kevinhng86.iblog.website, Programming World, and sites that have permission from me to posts the article in full content.

For the next chapter of infinity multiplication which is chapter three that is scheduled to be released this week, the chapter will contain the optimized source for multiplication that can be used for a production environment. With the source code, the tester which I used for testing hundreds of thousand of test cases against my code will also be released with the article. The only code that I do not release with the article is the benchmark test code, which tests how fast the program run versus 100,000 or test 1,000,000 cases.

This article is written for the R Programming Language. The source code to this is written for the R Programming environment.

Previous Chapter: Beyond Integer | Next Chapter: Optimised The Code |

#### How To Multiply Two String Of Digits Together With Precise Decimal Calculation

To simplify the explanation for this article, we are assuming that we are multiplying a string full of digits which name A to another string that is full of digits which name B. When multiplying two string of digits together to get a result value, the first challenge we face for applying the mathematical equation on the string is the decimal value or the digits behind the decimal. For addition and subtracting we can split the digit in A string into two parts. One part can contain the digits before the decimal and the other part can contain the digits behind the decimal. However, this technique will be very complicated when applying to multiplication. This is because of, every digit, whether if before or after the decimal in string A has to be multiplied to every digit in string B.

If we split A string into two parts, it’s can get very complicated to manipulate each part of A string to properly multiply to each part of B string, consider that they are both carry a decimal value. It’s doable, however complicated. We can have another simple solution, of which we can remove the decimal from both A and B string and treat the string as if the string does not contain the decimal. After we finished with the mathematical multiplication procedure we can inject the decimal into the correct position for our answer string.

In my opinion, the method of injecting the decimal into the correct position is highly efficient, is error proof and is simpler for loop controlling. This method is doable for multiplication due to how the decimal is placed in a multiplication procedure. Nevertheless, let first inspect the formula for calculating a decimal value in a mathematical multiplication procedure.

Formula: Calculating the decimal value for multiplication. Step 1: Count the amount of digit behind the decimal in A string that is not a trailing zero. Remove trailing zero. Step 2: Count the amount of digit behind the decimal in B string that is not a trailing zero. Remove trailing zero. Step 3: Add the number of digits that are behind the decimal for both A and B string together. In my description, this value is called the total amount of digits that need to be behind the decimal in our answer string. Step 4: Remove the decimal from both A and B string, then apply the multiplication procedure on A and B string. Step 5: Once the answer string is ready, count from right to left of the answer string. Using the value from step three and place the decimal in front of the total amount of digits that need to be behind the decimal in our answer string. If the answer string contains fewer digits than the count of step three, add a zero to the beginning of the answer string. Answer: After placing the decimal, we can remove leading and trailing zeroes. Trailing zeroes in decimal value do not alter the value of the number. Leading zeroes in a whole number do not alter the value of the number.

Example: 0.1 x 0.1 Step 1: (1 digits behind the decimal in A) + (1 digits behind the decimal in B) = (2 digits behind the decimal needed in the answer string) Step 2: 1 x 1 = 1 | Answer string: 1 Step 3: Answer string has only 1 digit, there need to be 2 digits behind the decimal. Add zero to beginning of the answer string Answer string: 01 Step 4. .01 | add zero in front of the decimal for formatting | answer string = 0.01 Answer: 0.1 * 0.1 = 0.01 Example: 9.125 x 33.100 Step 1: (3 digits behind the decimal in A) + (1 digits behind the decimal in B) = (4 digits behind the decimal needed in the answer string) Step 2: 9125 x 331 = 3020375 | Answer string: 3023075 Step 3: Answer string has more digits than the total digits needed to be behind the decimal. No need to modify. Answer string: 3020375 Step 4. 302.0375 Answer: 9.125 * 33.100 = 302.0375 Example: 152 x 239.55 Step 1: (0 digits behind the decimal in A) + (2 digits behind the decimal in B) = (2 digits behind the decimal needed in the answer string) Step 2: 152 x 23955 = 3641160 | Answer string: 3023075 Step 3: Answer string has more digits than the total digits needed to be behind the decimal. No need to modify. Answer string: 3641160 Step 4. 36411.60 | remove trailing zero for formatting | answer string is 36411.6 Answer: 152 * 239.55 = 36411.6

With the formula above put in perspective, calculating the decimal values in a multiplication procedure can be done through indexing the decimal. This method is more of a string manipulating method. The placement for the decimal is calculated before calculating any actual value. In my opinion, this method is the simplest method for calculating the decimal for any multiplication procedure, and this method offers the best precision placement for the decimal value as this method calculates the exact spot the decimal have to be placed at in the answer string.

Besides the formula, we still have shortcuts. Any numbers multiply by one will return itself as the value and any numbers that multiply by zero will always be zero. There is another shortcut that I do not apply to this formula and that is any number that multiplied to a .1 or .01 and so on will only need the decimal placement to be moved over to the left.

Nevertheless, let us look at some code block that we would need for our multiplication procedures with decimal supported. In R Programming language I couldn’t find a suitable function that can search for the index of the decimal. Therefore I wrote my own function. We do have the grepexpr() function in R to search for an index. However, when tested the grepexpr() function, the function will produce “1” as the placement if the match string is found at both the first and second position on the left side of the string.

This code block below is my function for searching the index of the decimal. For every while loop, I read both sides of the string, if the position within the string is found with a match the while loop will not execute in the next loop. This function will only look for one index and will exit. If a match is found on both side of the string in the same loop, the function will return the position on the left side of the string.

searchPos <- function(match, string){ i <- 1 len <- nchar(string) + 1 halflen <- len / 2 + 1 while (i < halflen && substr(string,i,i) != match && substr(string, len - i, len - i) != match){ i <- i + 1 } return(ifelse(substr(string, i, i) == match, i , ifelse(substr(string, len - i,len-i) == match, len - i, -1))) }

For the first procedure, we will need to search for the decimal in both our A string and B string. If the decimal is found, we need the position of the decimal. If the decimal is not found within the string, it is preferable that we will get a “-1” as the value for our variable. We are also declaring a position variable to later calculate the decimal position for our answer string.

aDecPos <- searchPos(".",a) bDecPos <- searchPos(".",b) oDecPos <- 0

To calculate how many digits behind the decimal in either our A or B string, we are subtracting the total length of the string to the decimal position in the string. Before getting the decimal position we have to remove any trailing zero in the string. This is why it is important that this code block below only executed if a decimal is found. Since we are removing trailing zeroes, we can have issues with strings that contains only zero digits behind the decimal. Thus if the total length of the string minus the decimal position go into the negative we have to set the value to zero. Zero also mean, there is not a digit behind the decimal.

After we calculated the number of digits that are behind the decimal in the string, we are also removing the decimal. This code block below is demonstrating the previous procedures.

if (aDecPos > -1){ a <- gsub("0+$", "", a) aDecPos <- ifelse( ((nchar(a) - aDecPos) > 0), (nchar(a) - aDecPos) , 0) a <- gsub("[.]", "", a) }

Since we removed the decimal and any trailing zero, if we want to use the shortcut of anything multiply by one will return itself as an answer, we would have to modify our code block for the shortcut procedure. This code block below will only execute if A string contained only a digit one and A string does not contain any digits behind the decimal. If we found that B string does, in fact, contained a decimal before this loop started, we placed the decimal back into B string at the correct position before we return B as the result.

To put the decimal into the correct position for B string, we get the digits from the zero position to the digit where the decimal is going to be placed. To calculate where the decimal is going to be placed, we get the total length of string B and subtract the value to the amount of digit B has after the decimal. We then add the decimal into the string and then we add the digits from where the decimal is placed to the end of the string. After placing the decimal and if the first character in B string is only the decimal, we can place a zero in front of the decimal. This is to correct input format such as “.123” or “.5774” or “.1111”.

After that, we check if A and B are different in positive and negative value. If they are, we can place a negative sign in front of B string and then we return B as our result. If B does not contain a decimal value, we simply return B. We also have to check for differences in negative and positive values in both A and B string. This code block below demonstrated the above procedures.

if (grepl(a, "1") && aDecPos < 1){ b <- paste(substr(b, 0,nchar(b) - bDecPos), "." ,substr(b, nchar(b) - bDecPos + 1, nchar(b)), sep="") b <- ifelse(substr(b,1,1) == ".", paste("0", b, sep=""), b) return(ifelse((isaNeg != isbNeg), paste("-", b, sep=""), b)) } return(ifelse((isaNeg != isbNeg), paste("-", b, sep=""), b)) }

After evaluating all the shortcuts for a multiplication procedure, we can then calculate the amount of digit we need to have behind the decimal in our answer string. This code block will only execute if either A or B was found with a decimal. If A is found with a decimal and B did not contain a decimal, the value for variable bDecPos would be a -1. Therefore if there was not a decimal in B we can set bDecPos as zero value. It’s would also mean, there is not a single digit behind the decimal in B string. We can then add up the total amount of digits behind the decimal in both A and B string together to get the total amount of digits that would need to be behind the decimal in our answer string. This code block below demonstrates the above procedures.

if (aDecPos > -1 || bDecPos > -1){ aDecPos <- ifelse(aDecPos > -1, aDecPos , 0) bDecPos <- ifelse(bDecPos > -1, bDecPos , 0) oDecPos <- aDecPos + bDecPos }

After the multiplication procedure and when we have an answer string, we can evaluate and place the decimal at the correct position in our answer string. We first check to see whether if our answer string contained fewer digits than the amount of digit that would need to be behind the decimal. This scenario occurs in events where “0.01 x 0.01” or “0.3 x 0.3” and so on.

To produce a new answer string with a decimal placement, we would grab the digits from the first position from the left side of our answer string to where the decimal is going to be placed. We then add the decimal behind these digits. After adding the decimal into the correct position, we add the rest of the digits in our answer string to the right side of the decimal. This new string’s value is now assigned as our answer string. To calculate where the decimal is going to be placed, we would need to subtract the length of our answer string to the amount of digit needed to be behind the decimal.

We then trim off any leading and trailing zero in our answer string. If the decimal is the last character in the string and there is not a digit behind the decimal, we would also remove the decimal. If the decimal is the first character in our answer string, we would place a zero in front of the decimal.

This code block below demonstrates the previously mentioned procedure in R Programming Language.

if (oDecPos > 0){ output <- ifelse((nchar(output) < oDecPos), paste("0", output, sep=""), output) output <- paste(substr(output, 0, nchar(output) - oDecPos), "." ,substr(output, nchar(output) - oDecPos + 1, nchar(output)), sep="") output <- gsub("^0+", "", output) output <- gsub("0+$", "", output) output <- gsub("[.]+$", "", output) output <- ifelse( substr(output,1,1) == '.' , paste("0", output, sep="") , output) }

This below is the fully functional code for this article which written for R Programming language. The code is capable of calculating numbers which can contain more than thousand of digits with precise decimal calculation.

# Written by Kevin Ng # The full tutorial on this subject can be found @ http://kevinhng86.iblog.website # This source code file is a part of Kevin Ng Z library. # To use this source code in your project please give the copyright credit. # This function only multiply and does not check to see if it is only number in the string, you must build a checker around it. # Notice: Version one and two of any infinity code from the libZ library are prototype. # They are not meant for production environment due to efficentcy. # Although are prototype these script were tested and ran through 300,000+ test cases without producing any errors. # This is version two of infinity multiplication for R, with precise decimal calculation. # a < - infiX <- function (a, b){ # This function is to be use until R platform have a search POS that is not grepexpr. # If grepexpr found a match on the first position of the string or the second on the left side, it will treat both position as position one. searchPos <- function(match, string){ i <- 1; len <- nchar(string) + 1; halflen <- len / 2 + 1; while ( i < halflen && substr(string,i,i) != match && substr(string, len - i, len - i) != match){ i <- i + 1; } return(ifelse(substr(string, i, i) == match, i , ifelse(substr(string, len - i,len-i) == match, len - i, -1))); } isaNeg <- ifelse(substr(a,1,1) == "-", 1 , 0); isbNeg <- ifelse(substr(b,1,1) == "-" , 1 , 0); a <- gsub("^[+-]+", "" , a); b <- gsub("^[+-]+", "" , b); a <- gsub("^0+", "", a); b <- gsub("^0+", "", b); aDecPos <- searchPos(".",a); bDecPos <- searchPos(".",b); oDecPos <- 0; if ( aDecPos > -1){ a < - gsub("0+$", "", a); aDecPos <- ifelse( ((nchar(a) - aDecPos) > 0), (nchar(a) - aDecPos) , 0); a < - gsub("[.]", "", a); } if ( bDecPos > -1){ b < - gsub("0+$", "", b); bDecPos <- ifelse( ((nchar(b) - bDecPos) > 0), (nchar(b) - bDecPos) , 0); b < - gsub("[.]", "", b); } if ( (nchar(a) < 1 || nchar(b) < 1 ) ){ return("0"); } if ( grepl(a, "1") && aDecPos < 1 ){ if ( bDecPos > 0 ){ b < - paste(substr(b, 0,nchar(b) - bDecPos), "." ,substr(b, nchar(b) - bDecPos + 1, nchar(b)), sep=""); b <- ifelse(substr(b,1,1) == ".", paste("0", b, sep="") , b); return(ifelse((isaNeg != isbNeg), paste("-", b, sep="") , b)); } return(ifelse((isaNeg != isbNeg), paste("-", b, sep="") , b)); } if ( grepl(b, "1") && bDecPos < 1 ){ if ( aDecPos > 0 ){ a < - paste(substr(a, 0,nchar(a) - aDecPos), "." ,substr(a, nchar(a) - aDecPos + 1, nchar(a)), sep=""); a <- ifelse(substr(a,1,1) == ".", paste("0", a, sep="") , a); return(ifelse((isaNeg != isbNeg), paste("-", a, sep="") , a)); } return(ifelse((isaNeg != isbNeg), paste("-", a, sep="") , a)); } if ( aDecPos > -1 || bDecPos > -1 ){ aDecPos < - ifelse(aDecPos > -1 , aDecPos , 0); bDecPos < - ifelse(bDecPos > -1 , bDecPos , 0); oDecPos < - aDecPos + bDecPos; } temp <- 0; outposition = 0; alen <- nchar(a); blen <- nchar(b); output <- ""; for ( i in blen:1){ y <- strtoi(substr(b,i,i)); leftover <- 0; outtemp <- ""; aidx = alen; while (aidx > 0){ temp < - strtoi(substr(a,aidx,aidx)) * y + leftover; leftover <- ifelse(temp > 9 , strtoi(gsub("\\d{1}$", "" , toString(temp))) , 0); outtemp < - paste(toString( substr(toString(temp), nchar(toString(temp)), nchar(toString(temp))) ), outtemp , sep=""); aidx <- aidx - 1; } outtemp <- ifelse(leftover > 0, paste(toString(leftover) , outtemp, sep="") , outtemp); if ( nchar(output) < 1){ output <- outtemp; outtemp <- ""; outposition <- outposition + 1; } else { tempadd <- 0; remainder <- 0; outlen <- nchar(output); outidx <- 0; cposition <- 0; tempaddstr <- ""; for (idx in nchar(outtemp):1){ cposition <- (outlen - outidx - outposition); x <- strtoi(substr(outtemp,idx,idx)); y <- ifelse(cposition > 0 , strtoi(substr(output,cposition,cposition)) , 0); tempadd < - x + y + remainder; remainder <- ifelse(tempadd > 9, 1 , 0); tempaddstr < - paste( toString( substr(toString(tempadd), nchar(toString(tempadd)), nchar(toString(tempadd))) ) , tempaddstr, sep=""); outidx <- outidx + 1; } tempaddstr <- ifelse(remainder > 0, paste(toString(remainder) , tempaddstr, sep="") , tempaddstr); output < - paste(tempaddstr, substr(output, nchar(output) - outposition + 1 , nchar(output) ), sep=""); outtemp <- ""; outposition <- outposition + 1; } } if ( oDecPos > 0 ){ output <- ifelse((nchar(output) < oDecPos), paste("0", output, sep=""), output); output <- paste(substr(output, 0, nchar(output) - oDecPos), "." ,substr(output, nchar(output) - oDecPos + 1, nchar(output)), sep=""); output <- gsub("^0+", "", output); output <- gsub("0+$", "", output); output <- gsub("[.]+$", "", output); output <- ifelse( substr(output,1,1) == '.' , paste("0", output, sep="") , output); } if ( isaNeg != isbNeg ){ output <- paste("-", output, sep=""); } return(output); } x = ".99999999999999999999999999"; y = "-.99999999999999999999999"; c = infiX(x,y); print(c);

Visit my blog at http://kevinhng86.iblog.website to find all my articles.