In the previous chapter of Infinity Multiplication, the chapter mainly concentrated onto the subject of storing two integer numbers in string format and how to apply a mathematical multiplication equation on the two numbers at the rate of one digit at a time. The previous chapter mainly discussed in regard to whole numbers, numbers that do not contain a fractional part. For this chapter, the subject is about how to apply a multiplication equation on large numbers that do contain a fractional part.

When computers store a number as an integer value. The value is stored in binary bits block that only store a binary value that represents the actual value of the number. Besides the value of the number, the binary bits block that is used to store the integer number may utilize one leftmost bit to defined if the value is a negative or a positive value, nevertheless, the bits block that is used to store the integer value does not store the fractional part of a number. The reason of why computers can not store a decimal point for numbers that do have the fractional part is because is because of the differential between the two numbering system. Nevertheless, when it comes to programming, a majority of programming languages if not all do have a data type that can store numbers with a fractional part. The most basic and most likely to be a built-in data type that is used by programming languages that can store a fractional part value is usually called a “float”.

When it comes to utilizing mathematical equations on float values, there are many methods of how to calculate a floating point value. There are floating point calculation formulas that do offer very precise answers. Nonetheless, there are circumstances where some floating point calculation formula does round off some of the digits that are on the right side of the decimal of the result value to get a near precision result value for the equation. These type of rounding can be very minor and would most likely have little affection.

Nonetheless, if we truly wanted to calculate a precise result value of numbers that do contain a fractional part and that are longer than thousand of digits, is there a solution to that? This is the second chapter of “Infinity Multiplication”, “Decimal, Precise Float Calculation”.

For a preview on the infinity subject, most of my readers ask me if this is truly an infinity library and is this truly an infinity subject? In my answer, Infinity is a subject that is very hard to explain in words. Since the values of infinity is endless and since it is endless, can we really calculate it? **This is my formula for calculating an infinity value “infC = infA = infAL”, of which can also be describe as “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 Subtraction subject. Chapter five of the infinity subject will only be available in full at http://kevinhng86.iblog.website, Programming World, and sites that are allowed to posts the articles in full.

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

This is the Ruby version of “Infinity Multiplication – Decimal, Precise Float Calculation”.

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

#### Precise Calculation With Fractional Part And Multiplication

For the purpose of simplification. This article explanations are base on a multiplication equation between two numbers that were stored in strings format. For the first number, this article defined the number as number A, string A, or simply A. For the second number, this article defined the number as number B, string B, or just B.

When applying a multiplication equation onto two string of digits and they do contain a fractional part then the first challenge we would face is the value of the fractional part, or in other words, the digits that are behind the decimal. For an addition or a subtraction equation, we can split the string into two parts. One part can hold the digits that are before the decimal and the other part can store the digits that are behind the decimal. Nonetheless, in my opinion, this technique can be somewhat complicated if to apply to a multiplication equation. This is because of the reason that every digit whether if before or behind the decimal in the first string has to be multiplied to every digit in the second string.

For the circumstance that we have two string of digits, one of them is A and the other one is B and if we were to split each string into two parts. Then it can get a bit complicated to manipulate each part of A string to properly multiply to each part of B string. It is doable, nevertheless, just a bit complicated. On the other hand, we do have another simple solution, of which we can remove the decimal from both A and B string. Then we would treat the strings as if they did not contain any decimal placement. One we completed the multiplication equation then we can inject the decimal into the answer string at the correct position.

In my opinion, the method of injecting the decimal into the answer string is highly efficient, is error proof, and is simpler for loop control. This method is doable for a multiplication equation due to the property that attaches to the decimal placement of a multiplication equation. Nevertheless, let first inspect the formula for calculating numbers that have a fractional part in a mathematical multiplication equation.

Formula: Multiplication formula for numbers with a fractional part. Step 1: Count the number of digits that are behind the decimal in A string and that are not trailing zeroes. Remove trailing zeroes. Step 2: Count the number of digits that are behind the decimal in B string and that are not trailing zeroes. Remove trailing zeroes. Step 3: Sum the number of digits that are behind the decimal in A string to the number of digits that are behind the decimal in B string. This value is defined as the total amount of digits that need to be behind the decimal in the answer string. Step 4: Remove the decimal from both A and B string, then apply the multiplication procedures on A and B string. Step 5: One the answer string is ready, starting from right to left of the answer string. Using the value of step three from above and place the decimal in front of the total amount of digits that need to be behind the decimal in the answer string. If the answer string contains fewer digits than the value of step three, add zeroes to the left side of the answer string until the amount of digit in the answer string is equal to the value from step three. Answer: After placing the decimal, we can remove leading and trailing zeroes. Leading zeroes that are before the decimal do not alter the value of the number. Trailing zeroes that are behind the decimal do not offer any values to the number.

Example: 0.1 x 0.1 Step 1: (1 digit behind the decimal in A) + (1 digit behind the decimal in B) = (2 digits that need to be behind the decimal in the answer string) Step 2: 1 x 1 = 1 | Answer string: 1 Step 3: Answer string has only 1 digit, nevertheless, there are 2 digits that need to be behind the decimal in the answer string. Therefore, add one zero to beginning of the answer string Answer string: 01 Step 4. .01 | add a 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 that need to be behind the decimal in the answer string) Step 2: 9125 x 331 = 3020375 | Answer string: 3023075 Step 3: Answer string has more digits than the total digit that needs to be behind the decimal. Therefore, no need to modify the answer string. 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 that need to be behind the decimal in the answer string) Step 2: 152 x 23955 = 3641160 | Answer string: 3023075 Step 3: Answer string has more digits than the total digit needs to be behind the decimal in the answer string. Therefore, no need to modify the answer string. Answer string: 3641160 Step 4. 36411.60 | remove the trailing zero for formatting | answer string is 36411.6 Answer: 152 * 239.55 = 36411.6

With the formula above in perspective, we can say that calculating the fractional part of a number in a multiplication equation can be done through indexing the decimal point. In a form of definition, this method of calculation is more of a string manipulation method. With this method, the placement for the decimal is calculated before calculating an actual result value. In my opinion, this method is the simplest method for calculating fractional part values for multiplication equations. Also, this method offers the best precision placement for the decimal. This is because this method calculates the exact decimal’s location for the answer string.

Besides the procedures, there are shortcuts that are available for our multiplication procedures. One of the shortcuts is if a number is multiplied by a value of one, then the equation will return the number as the result value. Currently, there is one shortcut that I decided to discontinue the support for in my infiX program and also in the explanation for the “Infinity Multiplication” series. That shortcut is when a value is multiplied by a value of zero. In that event, the equation will produce a value of zero as the result value. Due to efficiency on large scale multiplications, there is another shortcut that I do not apply to this formula. That shortcut is when a number multiplied to a value of .1 or .01 and so on then we will only need to reposition the decimal.

Let first inspect some of the code blocks that we would need for a multiplication equation that supported fractional part calculation.For the first procedure, we will need to evaluate the strings, A and B, for whether or not they do contain a decimal. If the decimal is found, we will need the position of the decimal. If the decimal is not found then it is preferable that a value of “-1” is assigned to the variable that was defined to hold the value of the position of the decimal. Also, another variable that needs to be declared to hold the value of the total amount of digit that needs to be behind the decimal for the answer string. For Ruby, we can use the strpos() function on a string to get the position of the decimal in that string. If the string doesn’t contain a decimal then the strpos() function will return a value of “-1”.

$aDecPos = strpos($a, "."); $bDecPos = strpos($b, "."); $oDecPos = 0;

To calculate how many digits that are behind the decimal in either A or B string, we subtract the length of the string to the position of the decimal. In my formula, before calculating the number of digits that are behind the decimal, we first remove any trailing zeroes in the string. This is why it is important that the code block below only execute when there is a decimal in the string. Since we are removing trailing zeroes, we can have issues with strings that contain only zeroes that are behind the decimal. Thus, if the equation of the total length of the string subtracts to the decimal’s position produce a negative result value, then we have to convert that negative value into a value to zero. In term of definition, a value of zero in this scenario also means that there aren’t any digits that are behind the decimal. After we had calculated the number of digits that are behind the decimal, we then remove the decimal.

One important key point that we have to remember here is at the beginning, variable aDecPos held a value that is the position of the decimal in the string. Nevertheless, after this code block below is executed, variable aDecPos would now store a value that representing the number of digits that are behind the decimal in A string. This code block below demonstrates the procedures of the previous explanations.

if (_aDecPos > -1) _a = _a.gsub(/0+$/, "") _aDecPos = (_a.length - 1 - _aDecPos) > 0? (_a.length - 1 - _aDecPos) : 0 _a = _a.gsub(/[.]/, "") end

Since we removed the decimal and any trailing zeroes, if we want to use the shortcut of when a number is multiplied by one, then we would have to modify our code from chapter 1 to accommodate the shortcut. This code block below will only execute in the condition that A string contained only a digit of one and A string does not contain any digits that are behind the decimal.

When it comes to returning the result value for this shortcut, if B string did contain a decimal then we placed the decimal back into B string at the correct position and then return B string as the result value. To place the decimal back into the correct position for B string, we get the digits from the first position to the position of where the decimal is going to be placed. To calculate where the decimal is going to be placed, we get the total length of B string and subtract the value to the number of digits that B has after the decimal. Then we add the decimal into the string and then we add the rest of the digits. After placing the decimal and if the first character in B string is the decimal, then we can place a zero in front of the decimal for formatting purposes. This is to correct input format such as “.123”, “.5774”, or “.1111”. Also, it is because we removed leading zeroes that were before the decimal. Therefore, input values such as “0.123”, “0.5774”, or “0.1111” would produce the same scenario as the previous.

Before returning the result value, we evaluate for whether or not A and B are different in then positive and the negative base. If they are, we can place a negative sign in front of B string and return B string as the result value. Otherwise, we can just return B string without any negative or positive sign.

Reverse back to when this procedure just started and in the event where B string did not contain a decimal, we can just simply return B string as the result value. Nonetheless, we do have to check for the differential in the negative and the positive base for both A and B string and we do have to place the negative sign in front of B string when it is necessary to do so. This code block below demonstrated the above procedures.

if (_a == "1" && _aDecPos < 1) if ( _bDecPos > 0) _b = _b[0...(_b.length - _bDecPos )] + "." + _b[(_b.length - _bDecPos)..._b.length] _b = _b[0] == "."? "0" + _b: _b return ((_isaNeg != _isbNeg)? "-" + _b : _b) end return ((_isaNeg != _isbNeg)? "-" + _b : _b) end

After evaluating the above shortcut, we can then calculate the number of digits that need to be behind the decimal in the answer string. The condition for this code block to execute is either A or B has to have a decimal. In the event where A was found with a decimal and B did not have a decimal then the value for variable bDecPos would be a value of -1. Therefore, if B did not have a decimal, we can assign to the variable bDecPos a value of zero. We also have to remember that if there wasn’t a decimal in B string, then our code block for calculating how many digits that supposed to be behind the decimal in B string from further above should not have been executed.

At this point in the program, a value of zero in bDecPos would also mean that there is not a single digit that is behind the decimal in B string. We can then add up the total amount of digits that are behind the decimal in both A and B string together to get the total amount of digits that need to be behind the decimal in the answer string. This code block below demonstrates the above procedures.

if (_aDecPos > -1 || _bDecPos > -1) _aDecPos = (_aDecPos > -1)? _aDecPos : 0 _bDecPos = (_bDecPos > -1)? _bDecPos : 0 _oDecPos = _aDecPos + _bDecPos end

In this chapter, I did not include the explanation for the multiplication procedures as chapter 1 did contain a very detail explanation of the procedures. Therefore, I would now fast forward to the event of when we got a result value from the multiplication procedures. After the multiplication procedures and when we have an answer string, we can evaluate and place the decimal into the answer string and at the correct position. For placing decimal’s procedure, we first check to see whether if the answer string does contain fewer digits than the number of digits that need to be behind the decimal. If this happens then we have to pad zeroes to the left of the answer string until the answer string has an amount of digits that is equal to the number of digits that need to be behind the decimal. This circumstance occurs in events where “0.01 x 0.01” or “0.3 x 0.3” and so on.

To replace the answer string’s value with a value that includes a fractional part, first, we would grab the digits from the first position in the answer string to where the decimal is going to be placed. To calculate where the decimal is going to be placed, we subtract the length of the answer string to the number of digits that need to be behind the decimal. Second, we place the decimal behind those digits. After placing the decimal into the correct position, we can add the rest of the digits to the value. This new value is now assigned as the value of our answer string.

We then trim off any leading and trailing zeroes in the answer string. If the decimal is the leftmost character in the string, we would also remove the decimal. If the decimal is the first character in the answer string then we would place a zero to the left of the decimal.

This code block below demonstrates the previously mentioned procedures in Ruby.

if (_oDecPos > 0) _output = (_output.length < _oDecPos)? "0" + _output : _output _output = _output[0...(_output.length - _oDecPos)] + "." + _output[(_output.length - _oDecPos)..._output.length] _output = _output.gsub(/0+$/,"") _output = _output.gsub(/[.]$/, "") _output = _output.gsub(/^0+/, "") _output = _output[0] == "."? "0" + _output : _output end

This below is the fully functional code for this article which was written in Ruby. The code is capable of calculating numbers, numbers of which can contain more than thousand of digits and whether or not if the numbers have a fractional part. Although this code is not meant for a production environment, it can calculate the fractional part/floating point value very precisely.

**Advertisement**

# 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 Ruby, with precise fractional part calculation. class LibZ def self.infiX(_a,_b) _isaNeg = _a[0] == "-"? 1 : 0 _isbNeg = _b[0] == "-"? 1 : 0 _a = _a.gsub(/^[+-]/,"") _b = _b.gsub(/^[+-]+/,"") _a = _a.gsub(/^0+/, "") _b = _b.gsub(/^0+/, "") _aDecPos = _a.index(".") || -1 _bDecPos = _b.index(".") || -1 _oDecPos = 0 if (_aDecPos > -1) _a = _a.gsub(/0+$/, "") _aDecPos = (_a.length - 1 - _aDecPos) > 0? (_a.length - 1 - _aDecPos) : 0 _a = _a.gsub(/[.]/, "") end if (_bDecPos > -1) _b = _b.gsub(/0+$/, "") _bDecPos = (_b.length - 1 - _bDecPos) > 0? (_b.length - 1 - _bDecPos) : 0 _b = _b.gsub(/[.]/, "") end if ( _a.length < 1 or _b.length < 1 ) return "0" end if (_a == "1" && _aDecPos < 1) if (_bDecPos > 0) _b = _b[0...(_b.length - _bDecPos)] + "." + _b[(_b.length - _bDecPos)..._b.length] _b = _b[0] == "."? "0" + _b : _b return ((_isaNeg != _isbNeg)? "-" + _b : _b) end return ((_isaNeg != _isbNeg)? "-" + _b : _b) end if (_b == "1" && _bDecPos < 1) if (_aDecPos > 0) _a = _a[0...(_a.length - _aDecPos )] + "." + _a[(_a.length - _aDecPos)..._a.length] _a = _a[0] == "."? "0" + _a : _a return ((_isaNeg != _isbNeg)? "-" + _a : _a) end return ((_isaNeg != _isbNeg)? "-" + _a : _a) end if (_aDecPos > -1 || _bDecPos > -1) _aDecPos = (_aDecPos > -1)? _aDecPos : 0 _bDecPos = (_bDecPos > -1)? _bDecPos : 0 _oDecPos = _aDecPos + _bDecPos end _temp = 0 _outposition = 0 _alen = _a.length _blen = _b.length _output = "" for _i in (_blen - 1).downto(0) _z = _b[_i].to_i _carryOverM = 0 _outtemp = "" _aidx = _alen - 1 while (_aidx > -1) do _temp = _a[_aidx].to_i * _z + _carryOverM _carryOverM = (_temp > 9)? _temp.to_s[0..-2].to_i : 0 _outtemp = _temp.to_s[-1] + _outtemp; _aidx = _aidx - 1 end _outtemp = (_carryOverM > 0)? _carryOverM.to_s + _outtemp : _outtemp; if (_output.length < 1) _output = _outtemp _outtemp = "" _outposition = _outposition + 1 else _tempadd = 0 _carryOverA = 0 _outlen = _output.length - 1 _outidx = 0 _cposition = 0 _tempaddstr = "" _x = 0 _y = 0 for _idx in (_outtemp.length - 1).downto(0) _cposition = (_outlen - _outidx - _outposition) _x = _outtemp.to_s[_idx].to_i _y = (_cposition > -1 )? _output.to_s[_cposition,1].to_i : 0 _tempadd = _x + _y + _carryOverA _carryOverA = (_tempadd > 9)? 1 : 0 _tempaddstr = _tempadd.to_s[-1] + _tempaddstr _outidx = _outidx + 1 end _tempaddstr = (_carryOverA > 0)? _carryOverA.to_s + _tempaddstr : _tempaddstr _output = _tempaddstr + _output[(_output.length - _outposition)..-1] _outtemp = "" _outposition = _outposition + 1 end end if (_oDecPos > 0) _output = (_output.length < _oDecPos)? "0" + _output : _output _output = _output[0...(_output.length - _oDecPos)] + "." + _output[(_output.length - _oDecPos)..._output.length] _output = _output.gsub(/0+$/,"") _output = _output.gsub(/[.]$/, "") _output = _output.gsub(/^0+/, "") _output = _output[0] == "."? "0" + _output : _output end if (_isaNeg != _isbNeg) _output = "-" + _output end return _output end end x = ".999999999999990000000000000000000000000000" y = "-0000000000000000000000000000.99999999999999" puts LibZ.infiX(x,y)

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

Original Post Name: "Working With Number – Infinity Multiplication – Decimal, Precise Float Calculation – Ruby".

Original Post Link: https://kevinhng86.iblog.website/2017/02/15/working-with-number-infinity-multiplication-decimal-precise-float-calculation-ruby/.

**Advertisement**