The previous chapter of Infinity Adding was discussing in regard to storing two integer numbers in string format and how to apply a mathematical addition equation on the two strings of digits by adding one digit at a time to produce an answer.

When we are discussing in regard to a mathematical calculation, one of the important components is how to deal with numbers that have a fractional part. In the computer world, numbers that carry a fractional part are often called float or floating point values. When calculating a floating point value, a majority of computer’s program will not calculate the precise value. Computer’s program will often round a floating point value to get a near precise calculation. Sometimes even on basic mathematical equations that only involved addition, the computer can’t generate a precise floating point calculation.

For example, when you are working within the Ruby two point three’s environment and apply this mathematical equation of 80075.40153176 + -85760.61572072. Ruby will give you the answer of -5685.2141889600025. Nevertheless, if we calculate the answer manually, we know that the correct answer is -5685.21418896. This type of method is the computer’s standard basic method for calculating values with a decimal placement. However, what happened if we truly need a precise decimal point value to be calculated without rounding the answer, and the numbers that involve in the equation have the possibility to have more than five hundred digits behind the decimal? This is chapter two of Infinity Adding, “Decimal, Precise Float Calculation”.

Note: The source code of chapter one and two of the Infinity Addition subject are prototypes. The prototypes purposes are to demonstrate the procedures for adding large numbers together. They are not meant for a production environment due to efficiency issue. Chapter three will have a production version of the source code.

This is a sample log of the result I got from executing the script that attaches to this article compare to Ruby’s built-in float calculation. For each answer, the one of the left is Ruby’s answer, and the one on the right is the answer provided by the script at the end of this article.

Question: 57290.41029489 + -43002.67676989 Ruby Answer: 14287.733525000003 | infiA:14287.733525 Question: 86510.52070696 + -14773.729795 Ruby Answer: 71736.79091196001 | infiA:71736.79091196 Question: 67822.1881149 + -20525.23899075 Ruby Answer: 47296.94912414999 | infiA:47296.94912415 Question: 79288.20277383 + -78325.84733581 Ruby Answer: 962.355438019993 | infiA:962.35543802 Question: 21755.42232231 + -72515.18989064 Ruby Answer: -50759.767568330004 | infiA:-50759.76756833

### How To Add Two Floating Numbers Together In String Format

When storing numbers with a fractional part in string format, the first challenge we would have when we are applying a mathematical equation on the string is the digits behind the decimal. The string of number can be split into an array, where one index of the array holds the digits before the decimal and the other index holds the digits behind the decimal. Nevertheless, there is a high possibility that the amount of digit behind the decimal that each string has can vary. That can be solved by padding zeroes on the right of the shorter string to make both strings of number contain the exact same amount of digits behind the decimal.

Besides array, we can also split one string with the fractional part into two strings. After the split, one string can carry the digits before the decimal, and the other string can carry the digits behind the decimal. Thus, if we were going to add two strings of numbers that contain a fractional part together, we can have up to four strings. An example of this would be if we were to add A and B together where both A and B does contain a fractional part. Then we would split A into two. Where A1 can contain the digits before the decimal and A2 contains the digits behind the decimal. The same scenario would also apply to B1 and B2.

When it comes to calculating the digits behind the decimal, we can pad zeroes to the right of B2 if B2 is shorter than A2 to produce the equivalent amount of digits behind the decimal or vice-versa if A2 is shorter than B2. Another method to this would be, instead of padding zeroes, we can read the longer string first from the right. As long as the position we read is not less than or equal to the largest position of the shorter string, we would not read from the shorter string, instead, we would assign a value of zero in lieu of the shorter string’s digit. The addition formula for calculating the digits behind the decimal would be the same as calculating the digits before the decimal. We only have one additional procedure when it comes to adding values that are behind the decimal, and it is the final carry-over value from the equation have to be carried over to the equation of adding the two strings of digits that are before the decimal.

In this chapter, the majority of the information is in regard to the source code and explanations of the programming procedures for the source code.

Let first start with evaluating the input value of the string. First I use a conditional statement to test if the string is positive or negative in value by looking at the first character in the string. If the first character in the string is a negative sign, the variable isaNeg will be assigned with the value of one, of which can also be equal to a boolean value of true. For anything else, we assign a zero value to isaNeg. To get a character by position in Ruby, we could use the <string_variable_name>[<position>] option. Which can grab a character using the inputted position as a position to grab from in the string, with the zero position being the first position in a string.

Note that you can also use a boolean declaration here with a true or false value. Nevertheless, I used a digit value here for isaNeg in the prototype to demonstrates another method for evaluating and storing a true or false value.

_isaNeg = (_a[0] == "-")? 1 : 0

After evaluating whether if the string can be a negative value or not, I removed any plus or minus sign using Ruby’s gsub() function with a regex pattern to search for and remove any negative or positive sign at the beginning of the string. We would also want to remove leading zeroes. This is because leading zeroes before the decimal do not offer any additional value to the number.

_a = _a.gsub(/^[-+]+/, "") _a = _a.gsub(/^0+/, "")

We would then need to initialize a third evaluation on the input. If the user input .123 without putting a zero in front of the decimal then we have to append a single zero to the front of the decimal. Therefore, we would evaluate whether if the first character of the string is a decimal. If it is a decimal, we add a zero to the string. If the first character is not a decimal, the string will be itself. We can just simply check the first position of the string to see whether if the position does contain a decimal using a regex pattern as a matching condition. I’m using a regex conditional statement here instead of the “[]” option is because I just want to demonstrate an alternative method that can produce the same result for the same procedure.

_a = (_a =~ /^[.]{1}/)? "0" + _a : _a

After the above evaluation, I then evaluate if the string does contain a decimal by using regex. If the string does contain a decimal. I will use Ruby’s gsub() function with a regex pattern that can evaluate and remove all the digits that are before the decimal, including the decimal from A string. The leftover digits are then assigned to a variable name adec. Variable adec is now holding the digits that are behind the decimal. Since I did the previous procedure through a variable assignment statement, the value of string A has not changed. On the third code line below, I removed all the digits that are behind the decimal and including the decimal in the value of variable A. Variable A is now holding the digits that are before the decimal.

if (_a =~ /[.]/) _adec = _a.gsub(/^[0-9]{0,}[.]/, "") _a = _a.gsub(/[.][0-9]{0,}$/, "") end

When it comes to the strings that contain the digits behind the decimal, in the event where they do not contain a value, it would be very inefficiency to add the empty strings together. Also, the digits behind the decimal have to be added together first before the digits before the decimal. To be able to execute the equation efficiently, we would have to wrap our code block for adding the digits behind the decimal right before the code block for adding the digits before the decimal. On the first two lines of the below code, adeclen and bdeclen are the lengths of the strings that contain the digits behind the decimal. The if statement code block will only execute if either one of the lengths of the strings that contain the digits behind the decimal is higher than zero. In others word, either adec or bdec need to have a length for the code block to execute.

_adeclen = _adec.length _bdeclen = _bdec.length if (_adeclen > 0 or _bdeclen > 0) # Equation code goes here end

While reading through the strings in a while loop or in a for loop, let assume the “_i” variable is the index count and we will use it as the read position value to get a digit from our strings. We would only read the string that contains the digits behind the decimal if the current position value in the “_i” variable is lower than the string’s maximum length. If the read position is within the string length, we would get a digit from that string at that position. Then we would convert the digit that we just obtained to an integer format. For anything else, we assign a value of zero in lieu of the string’s value.

_x = _i < _adeclen? _adec[_i].to_i : 0

When calculating the carry-over value for the next equation, we simply evaluate if the temporary answer’s value is higher than nine. If the temporary result value is higher than nine then we would assign one to the carry-over value. In a mathematical addition equation that only involves two sets of digits then the carry-over value can never be larger than the value of one. In the temporary result value, for anything else that is below the value of nine, we would assign a zero value to the carry-over value.

When assigning a value to the output, it is a constant that we will always assign the rightmost digit from the temporary answer to the left of the output string. We can base our evaluations on two conditions to get the rightmost digit from the temporary answer. If the result value is higher than nine, we take a value of ten and subtract to the temporary result value. For anything else, we simply keep the result value. This method can only be applied to a mathematical addition equation. Also, we can only apply this method when adding only two sets of digits together. This is because the carry-over value can never be larger than a value of one.

_leftover = _temp > 9 ? 1 : 0 _temp = _temp > 9? _temp - 10 : _temp _output = _temp.to_s + _output _output = (_aidx < 1 and _bidx < 1)? _leftover.to_s + _output : _output

After adding the entire two strings of digits behind the decimal together and the output string contained the full result value for the equation. We would then need to append a decimal point to the front of the output string before going into our next calculation. We then check for any zeroes to the right of the output string and remove all ending zeroes. As opposed to a whole number, trailing zeroes to the right side of the digits that are behind a decimal point do not provide any additional value. After removing all the zeroes, if the last character is only the decimal then we would also remove the decimal. The previous two procedures are done through regex on line two and three.

_output = "." + _output _output = _output.gsub(/[0]{1,}$/, "") _output = _output.gsub(/[.]$/ , "")

The above explanations are important code lines for adding a positive number to a positive number. Let discuss some important code lines for adding a positive number to a negative number. Or a negative number to a positive number. The principles for adding a positive value to a negative value can be described as subtracting the two values. The result value from this type of equation will carry the same negative or positive base as the larger value.

The example below is for the event of when the first string of input being the higher value string. In the first code line, we are subtracting the first string’s digit to the second string’s digit then to any carry-over value. For the second code line, we are assigning a carry-over value bases on a condition. If the result value is less than zero then we assign a value of one to the carry-over value. Otherwise, a value of zero is assigned to the carry-over value. This is easy to achieve when we are only dealing with two sets of digits. If we were dealing with more than two sets of digits then we would have to implement another method.

On the third code line, if the result value is less than zero, or in others word, a negative value. Then we would take a value of ten and add to the result value. Otherwise, we would not alter the result value. We then place the result value to the left of the output string, the code statement for this is on the fourth code line.

_temp = _x - _y - _carryOver _carryOver = _temp < 0? 1 : 0 _temp = _temp < 0? 10 + _temp : _temp _output = _temp.to_s + _output

The above is if the first input string is higher in value. When it’s come to the second input string that is higher in value, the equation’s procedures do not change, nevertheless, there are differences between the two equation. When comparing the first line of code to the above equation’s procedure, we are still subtracting the first string’s digit to the second string’s digit. Nonetheless, instead of subtracting to the carry-over value, we are now adding to the carry-over value. The main change in how we are assigning the carry-over value is the temporary result value has to be larger than zero for us to assign a value of one to the carry-over value.

On the third code line below, the ending is very important. The temporary result value that does not need to be modified is now negative in value. If we are going to convert a negative integer value to a string type format and then placing the value to the output string, we would have a minus sign between every digit. Thus, we can either subtract the temporary result value to itself twice to reach its positive value, convert the temporary result value to a string type and grab the rightmost digit, or simply, multiply the temporary result value to a negative value of one.

_temp = _x - _y + _carryOver _carryOver = _temp > 0? 1 : 0; _temp = _temp > 0? 10 - _temp : (_temp - _temp - _temp) _output = _temp.to_s + _output

The code is below is the full function of this tutorial.

**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 version 2 of infiA from Kevin Ng's LibZ library. # This is not a production version and is a prototype. # This version has been tested, but would be too slow in a production environment. # This version of infiA support mathematical addition with the decimal. class LibZ def self.infiA(_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+/, "") _a = (_a =~ /^[.]{1}/)? "0" + _a : _a _b = (_b =~ /^[.]{1}/)? "0" + _b : _b _adec = "" _bdec = "" if (_a =~ /[.]/) _adec = _a.gsub(/^[0-9]{0,}[.]/, "") _a = _a.gsub(/[.][0-9]{0,}$/, "") end if (_b =~ /[.]/) _bdec = _b.gsub(/^[0-9]{0,}[.]/,"") _b = _b.gsub(/[.][0-9]{0,}$/, "") end _aidx = _a.length - 1 _bidx = _b.length - 1 _adeclen = _adec.length _bdeclen = _bdec.length _x = 0 _y = 0 _carryOver = 0 _temp = 0 _output = "" if (_isaNeg == _isbNeg) if (_adeclen > 0 or _bdeclen > 0) _i = (_adeclen > _bdeclen)? _adeclen - 1 : _bdeclen - 1 while (_i > -1) do _x = (_i < _adeclen)? _adec[_i].to_i : 0 _y = (_i < _bdeclen)? _bdec[_i].to_i : 0 _temp = _x + _y + _carryOver _carryOver = _temp > 9? 1 : 0 _temp = _temp > 9? _temp - 10 : _temp _output = _temp.to_s + _output _i = _i - 1 end _output = "." + _output _output = _output.gsub(/[0]{1,}$/, "") _output = _output.gsub(/[.]$/ , "") end while (_aidx > -1 or _bidx > -1) do _x = _aidx > -1? _a[_aidx].to_i : 0 _y = _bidx > -1? _b[_bidx].to_i : 0 _temp = _x + _y + _carryOver _carryOver = _temp > 9 ? 1 : 0 _temp = _temp > 9? _temp - 10 : _temp _output = _temp.to_s + _output _output = (_aidx < 1 and _bidx < 1)? _carryOver.to_s + _output : _output _aidx = _aidx - 1 _bidx = _bidx - 1 end _output = _output.gsub(/^0+/, "") _output = _output.length < 1? "0" : _output return (_isaNeg == 1 and _isbNeg == 1)? "-" + _output : _output elsif (_isaNeg != _isbNeg) _larger = (_a.length > _b.length) ? "a" : ((_b.length > _a.length)? "b" : "1") if (_larger == "1") _larger = "" for _i in 0.._a.length _larger = (_a[_i].to_i > _b[_i].to_i)? "a" : _larger _larger = (_b[_i].to_i > _a[_i].to_i)? "b" : _larger _larger = ( _i == _a.length - 1 and _larger.length < 1)? "0" : _larger if (_larger.length > 0) then break end end if ((_adeclen > 0 or _bdeclen > 0) and _larger == "0") _max = (_adeclen > _bdeclen)? _adeclen : _bdeclen for _i in 0.._max _x = (_i < _adeclen)? _adec[_i].to_i : 0 _y = (_i < _bdeclen)? _bdec[_i].to_i : 0 _larger = (_x > _y)? "a" : ((_y > _x)? "b" : "0") if (_larger == "a" or _larger == "b" ) then break end end end end if (_larger == "0") return _larger elsif (_larger == "a") if (_adeclen > 0 or _bdeclen > 0) _i = (_adeclen > _bdeclen)? _adeclen - 1 : _bdeclen - 1 while (_i > -1) do _x = (_i < _adeclen)? _adec[_i].to_i : 0 _y = (_i < _bdeclen)? _bdec[_i].to_i : 0 _temp = _x - _y - _carryOver _carryOver = _temp < 0? 1 : 0 _temp = _temp < 0? 10 + _temp : _temp _output = _temp.to_s + _output _i = _i - 1 end _output = "." + _output _output = _output.gsub(/[0]{1,}$/, "") _output = _output.gsub(/[.]$/ , "") end while (_aidx > -1) do _x = _a[_aidx].to_i _y = _bidx > -1? _b[_bidx].to_i : 0 _temp = _x - _y - _carryOver _carryOver = _temp < 0? 1 : 0 _temp = _temp < 0? 10 + _temp : _temp _output = _temp.to_s + _output _aidx = _aidx - 1 _bidx = _bidx - 1 end _output = _output.gsub(/^0+/, "") _output = (_output =~ /^[.]{1}/) ? "0" + _output : _output return _isaNeg == 1? "-" + _output : _output elsif (_larger == "b") if (_adeclen > 0 || _bdeclen > 0) _i = (_adeclen > _bdeclen)? _adeclen - 1 : _bdeclen - 1 while (_i > -1) do _x = (_i < _adeclen )? _adec[_i].to_i : 0 _y = (_i < _bdeclen )? _bdec[_i].to_i : 0 _temp = _x - _y + _carryOver _carryOver = _temp > 0? 1 : 0 _temp = _temp > 0? 10 - _temp : (_temp - _temp - _temp) _output = _temp.to_s + _output _i = _i - 1 end _output = "." + _output _output = _output.gsub(/[0]{1,}$/, "") _output = _output.gsub(/[.]$/ , "") end while (_bidx > -1) do _x = _aidx > -1? _a[_aidx].to_i : 0 _y = _b[_bidx].to_i _temp = _x - _y + _carryOver _carryOver = _temp > 0? 1 : 0 _temp = _temp > 0? 10 - _temp : (_temp - _temp - _temp) _output = _temp.to_s + _output _aidx = _aidx - 1; _bidx = _bidx - 1; end _output = _output.gsub(/^0+/, "") _output = (_output =~ /^[.]{1}/) ? "0" + _output : _output return (_isaNeg == 0)? "-" + _output : _output end end end end # Test case c = "99999999999999999999999999999999999999999999999999.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" d = "99999999999999999999999999999999999999999999999999.9999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999" puts LibZ.infiA(c,d)

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

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

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

**Advertisement**