Working With Number – Infinity Multiplication – Optimised The Code – R

Thank you to all my readers for following up on my contents. Sorry for the delay in release for this chapter of infinity multiplication for the R Programming Language. I had spent a couple of days testing the source code against the as.numeric() function and found a bug that associate with the as.numeric() function. As first I thought my function was producing errors so I had to re-manual test my function and the as.numeric() function results. A majority of R programmers knows that the as.numeric() function can handle mathematical equation up 300 digits in length. It actually a couple digits more than 300. After the limit, the as.numeric() function will produce an Infi value as a result.

That, however, is not the bug. The bug here is when the as.numeric() function doing calculations that would produce 16 digits in length result, the as.numeric() function will produce incorrect answers. Before we are going into this chapter I will display the error log I got from as.numeric() result. I manually test some cases. Not all of them but there were two tests, each test comprised of 5000 random cases.

I only show one of the test cases which I did the manual test on. I had to look for others library that can calculate large data to also verify the actual results. The version of R that produced this error was R version 3.0.2.

Native calculation = as.numeric();
[1] "Case #4995 +81252317553 * -5201267321788"
[1] "Unmatch Case # 4996"
[1] "Question: +81252317553 * -5201267321788"
[1] "         Native Calculation: -4226 15024 10796 03851 42784 | 
                           infiX: -4226 15024 10796 04117 44764"
                            Ruby: -4226 15024 10796 04117 44764
                          BigNum: -4226 15024 10796 04117 44764
    Manual Input Into as.numeric: -4226 15024 10796 03851 42784


"Case #4900 +195401837748 * -604299545158"
[1] "Unmatch Case # 4901"
[1] "Question: +195401837748 * -604299545158"
[1] "Native Multiplication: -118081241674153715564544 | infiX: -118081241674153715024184"
[1] ""
[1] "Case #4901 +445427940952 * -6524032439925"
[1] "Unmatch Case # 4902"
[1] "Question: +445427940952 * -6524032439925"
[1] "Native Multiplication: -2905986336419845379194880 | infiX: -2905986336419845387308600"
[1] ""
[1] "Case #4902 +993267551770 * -9228714121241"
[1] "Unmatch Case # 4903"
[1] "Question: +993267551770 * -9228714121241"
[1] "Native Multiplication: -9166582281190274836201472 | infiX: -9166582281190275024146570"
[1] ""
[1] "Case #4903 +321164857083 * -1740799229120"
[1] "Unmatch Case # 4904"
[1] "Question: +321164857083 * -1740799229120"
[1] "Native Multiplication: -559083535630521405014016 | infiX: -559083535630521371856960"
[1] ""
[1] "Case #4904 +82834620603 * -3285487240996"
[1] "Unmatch Case # 4905"
[1] "Question: +82834620603 * -3285487240996"
[1] "Native Multiplication: -272152089103900889579520 | infiX: -272152089103900887840588"
[1] ""
[1] "Case #4905 +274056984672 * -4136066416928"
[1] "Unmatch Case # 4906"
[1] "Question: +274056984672 * -4136066416928"
[1] "Native Multiplication: -1133517890626410894065664 | infiX: -1133517890626410857327616"
[1] ""
[1] "Case #4906 +825638017333 * -7315808339113"
[1] "Unmatch Case # 4907"
[1] "Question: +825638017333 * -7315808339113"
[1] "Native Multiplication: -6040209492293485229768704 | infiX: -6040209492293485035845629"
[1] ""
[1] "Case #4907 +397917942738 * -3683383422692"
[1] "Unmatch Case # 4908"
[1] "Question: +397917942738 * -3683383422692"
[1] "Native Multiplication: -1465684353872853746057216 | infiX: -1465684353872853705810696"
[1] ""
[1] "Case #4908 +598338513467 * -5011186580057"
[1] "Unmatch Case # 4909"
[1] "Question: +598338513467 * -5011186580057"
[1] "Native Multiplication: -2998385929017084985999360 | infiX: -2998385929017084968127619"
[1] ""
[1] "Case #4909 +670385439599 * -6676417512503"
[1] "Unmatch Case # 4910"
[1] "Question: +670385439599 * -6676417512503"
[1] "Native Multiplication: -4475773089065785731579904 | infiX: -4475773089065785733806297"
[1] ""
[1] "Case #4910 +478743027334 * -2802092764934"
[1] "Unmatch Case # 4911"
[1] "Question: +478743027334 * -2802092764934"
[1] "Native Multiplication: -1341482373155201669398528 | infiX: -1341482373155201598705956"
[1] ""
[1] "Case #4911 +601108357002 * -381800847341"
[1] "Unmatch Case # 4912"
[1] "Question: +601108357002 * -381800847341"
[1] "Native Multiplication: -229503680047119920529408 | infiX: -229503680047119930431682"
[1] ""
[1] "Case #4912 +378762267680 * -700244191881"
[1] "Unmatch Case # 4913"
[1] "Question: +378762267680 * -700244191881"
[1] "Native Multiplication: -265226078046596597022720 | infiX: -265226078046596604706080"
[1] ""
[1] "Case #4913 +10513196246 * -2191863731445"
[1] "Unmatch Case # 4914"
[1] "Question: +10513196246 * -2191863731445"
[1] "Native Multiplication: -23043493553171127599104 | infiX: -23043493553171126155470"
[1] ""
[1] "Case #4914 +113695298332 * -1983071387481"
[1] "Unmatch Case # 4915"
[1] "Question: +113695298332 * -1983071387481"
[1] "Native Multiplication: -225465893013305478348800 | infiX: -225465893013305464981692"
[1] ""
[1] "Case #4915 +251917060018 * -6006535172928"
[1] "Unmatch Case # 4916"
[1] "Question: +251917060018 * -6006535172928"
[1] "Native Multiplication: -1513148681658731054759936 | infiX: -1513148681658730984792704"
[1] ""
[1] "Case #4916 +840987976205 * -8574399619867"
[1] "Unmatch Case # 4917"
[1] "Question: +840987976205 * -8574399619867"
[1] "Native Multiplication: -7210966983484870135644160 | infiX: -7210966983484869641264735"
[1] ""
[1] "Case #4917 +323453919285 * -1013486807833"
[1] "Unmatch Case # 4918"
[1] "Question: +323453919285 * -1013486807833"
[1] "Native Multiplication: -327816280137227455954944 | infiX: -327816280137227487759405"
[1] ""
[1] "Case #4918 +152710110484 * -8359581423556"
[1] "Unmatch Case # 4919"
[1] "Question: +152710110484 * -8359581423556"
[1] "Native Multiplication: -1276592602791230828445696 | infiX: -1276592602791230760161104"
[1] ""
[1] "Case #4919 +575448116582 * -355726256524"
[1] "Unmatch Case # 4920"
[1] "Question: +575448116582 * -355726256524"
[1] "Native Multiplication: -204702004335501188792320 | infiX: -204702004335501190080968"
[1] ""
[1] "Case #4920 +53661035942 * -1693687866010"
[1] "Unmatch Case # 4921"
[1] "Question: +53661035942 * -1693687866010"
[1] "Native Multiplication: -90885045452491886428160 | infiX: -90885045452491890131420"
[1] ""
[1] "Case #4921 +969162128654 * -7007592694942"
[1] "Unmatch Case # 4922"
[1] "Question: +969162128654 * -7007592694942"
[1] "Native Multiplication: -6791493452970208677330944 | infiX: -6791493452970209179068068"
[1] ""
[1] "Case #4922 +586267735571 * -7324250789363"
[1] "Unmatch Case # 4923"
[1] "Question: +586267735571 * -7324250789363"
[1] "Native Multiplication: -4293971925033955564191744 | infiX: -4293971925033955303531273"
[1] ""
[1] "Case #4923 +23486866102 * -2680183522370"
[1] "Unmatch Case # 4924"
[1] "Question: +23486866102 * -2680183522370"
[1] "Native Multiplication: -62949111518690910666752 | infiX: -62949111518690911701740"
[1] ""
[1] "Case #4924 +221838293011 * -4565494481762"
[1] "Unmatch Case # 4925"
[1] "Question: +221838293011 * -4565494481762"
[1] "Native Multiplication: -1012801502585222217072640 | infiX: -1012801502585222151565382"
[1] ""
[1] "Case #4925 +247189524393 * -3746229354672"
[1] "Unmatch Case # 4926"
[1] "Question: +247189524393 * -3746229354672"
[1] "Native Multiplication: -926028652448466941771776 | infiX: -926028652448466992514096"
[1] ""
[1] "Case #4926 +34971017754 * -5184207526890"
[1] "Unmatch Case # 4927"
[1] "Question: +34971017754 * -5184207526890"
[1] "Native Multiplication: -181297013463290635878400 | infiX: -181297013463290622405060"
[1] ""
[1] "Case #4927 +239667480752 * -8473345981539"
[1] "Unmatch Case # 4928"
[1] "Question: +239667480752 * -8473345981539"
[1] "Native Multiplication: -2030785484935534714290176 | infiX: -2030785484935534829837328"
[1] ""
[1] "Case #4928 +91571199319 * -344994455565"
[1] "Unmatch Case # 4929"
[1] "Question: +91571199319 * -344994455565"
[1] "Native Multiplication: -31591556054492504915968 | infiX: -31591556054492503760235"
[1] ""
[1] "Case #4929 +529336519476 * -1498905883477"
[1] "Unmatch Case # 4930"
[1] "Question: +529336519476 * -1498905883477"
[1] "Native Multiplication: -793425623381813974007808 | infiX: -793425623381813997098052"
[1] ""
[1] "Case #4930 +595485755576 * -4763432477669"
[1] "Unmatch Case # 4931"
[1] "Question: +595485755576 * -4763432477669"
[1] "Native Multiplication: -2836556188099982217183232 | infiX: -2836556188099982212232344"
[1] ""
[1] "Case #4931 +64443454060 * -2544917670596"
[1] "Unmatch Case # 4932"
[1] "Question: +64443454060 * -2544917670596"
[1] "Native Multiplication: -164003284991535531163648 | infiX: -164003284991535538819760"
[1] ""
[1] "Case #4932 +362055222959 * -5194188112640"
[1] "Unmatch Case # 4933"
[1] "Question: +362055222959 * -5194188112640"
[1] "Native Multiplication: -1880582935212862516232192 | infiX: -1880582935212862606101760"
[1] ""
[1] "Case #4933 +4293939715 * -5098760292370"
[1] "Unmatch Case # 4934"
[1] "Question: +4293939715 * -5098760292370"
[1] "Native Multiplication: -21893769316672552828928 | infiX: -21893769316672554474550"
[1] ""
[1] "Case #4934 +210339582302 * -1308748935199"
[1] "Unmatch Case # 4935"
[1] "Question: +210339582302 * -1308748935199"
[1] "Native Multiplication: -275281704367944940650496 | infiX: -275281704367944925248098"
[1] ""
[1] "Case #4935 +951250585439 * -8210792938967"
[1] "Unmatch Case # 4936"
[1] "Question: +951250585439 * -8210792938967"
[1] "Native Multiplication: -7810521590110766246133760 | infiX: -7810521590110766145901513"
[1] ""
[1] "Case #4936 +456457380401 * -9599580871293"
[1] "Unmatch Case # 4937"
[1] "Question: +456457380401 * -9599580871293"
[1] "Native Multiplication: -4381799537457951733186560 | infiX: -4381799537457951921728493"
[1] ""
[1] "Case #4937 +348063750378 * -1704739299521"
[1] "Unmatch Case # 4938"
[1] "Question: +348063750378 * -1704739299521"
[1] "Native Multiplication: -593357954008043889885184 | infiX: -593357954008043918968938"
[1] ""
[1] "Case #4938 +415246614228 * -998056518124"
[1] "Unmatch Case # 4939"
[1] "Question: +415246614228 * -998056518124"
[1] "Native Multiplication: -414439589959177531817984 | infiX: -414439589959177518268272"
[1] ""
[1] "Case #4939 +320657664238 * -3289479317399"
[1] "Unmatch Case # 4940"
[1] "Question: +320657664238 * -3289479317399"
[1] "Native Multiplication: -1054796754476373976809472 | infiX: -1054796754476373973476962"
[1] ""
[1] "Case #4940 +357180877633 * -6473287365068"
[1] "Unmatch Case # 4941"
[1] "Question: +357180877633 * -6473287365068"
[1] "Native Multiplication: -2312134462225598231085056 | infiX: -2312134462225598306724044"
[1] ""
[1] "Case #4941 +452841392093 * -595476660437"
[1] "Unmatch Case # 4942"
[1] "Question: +452841392093 * -595476660437"
[1] "Native Multiplication: -269656479871181741096960 | infiX: -269656479871181737724641"
[1] ""
[1] "Case #4942 +996531430738 * -2780030455013"
[1] "Unmatch Case # 4943"
[1] "Question: +996531430738 * -2780030455013"
[1] "Native Multiplication: -2770387726829318081347584 | infiX: -2770387726829318034389594"
[1] ""
[1] "Case #4943 +972780743638 * -1145846296991"
[1] "Unmatch Case # 4944"
[1] "Question: +972780743638 * -1145846296991"
[1] "Native Multiplication: -1114657212881753560055808 | infiX: -1114657212881753581793258"
[1] ""
[1] "Case #4944 +8704453611 * -8360631959966"
[1] "Unmatch Case # 4945"
[1] "Question: +8704453611 * -8360631959966"
[1] "Native Multiplication: -72774733054168056987648 | infiX: -72774733054168056137226"
[1] ""
[1] "Case #4945 +142232072155 * -4660852690689"
[1] "Unmatch Case # 4946"
[1] "Question: +142232072155 * -4660852690689"
[1] "Native Multiplication: -662922736205903775662080 | infiX: -662922736205903744664795"
[1] ""
[1] "Case #4946 +493764231676 * -6494804639004"
[1] "Unmatch Case # 4947"
[1] "Question: +493764231676 * -6494804639004"
[1] "Native Multiplication: -3206902222463530751229952 | infiX: -3206902222463530601890704"
[1] ""
[1] "Case #4947 +283424581926 * -6143399861063"
[1] "Unmatch Case # 4948"
[1] "Question: +283424581926 * -6143399861063"
[1] "Native Multiplication: -1741190537226027372904448 | infiX: -1741190537226027260947338"
[1] ""
[1] "Case #4948 +774600439036 * -9846292249017"
[1] "Unmatch Case # 4949"
[1] "Question: +774600439036 * -9846292249017"
[1] "Native Multiplication: -7626942298965332365148160 | infiX: -7626942298965332039427612"
[1] ""
[1] "Case #4949 +881310215895 * -696273304789"
[1] "Unmatch Case # 4950"
[1] "Question: +881310215895 * -696273304789"
[1] "Native Multiplication: -613632776565518785052672 | infiX: -613632776565518727421155"
[1] ""
[1] "Case #4950 +39997966020 * -5245861193945"
[1] "Unmatch Case # 4951"
[1] "Question: +39997966020 * -5245861193945"
[1] "Native Multiplication: -209823777781048735170560 | infiX: -209823777781048739748900"
[1] ""
[1] "Case #4951 +83089082826 * -1506709878521"
[1] "Unmatch Case # 4952"
[1] "Question: +83089082826 * -1506709878521"
[1] "Native Multiplication: -125191141891183768240128 | infiX: -125191141891183767380346"
[1] ""
[1] "Case #4952 +200984144411 * -3395871955557"
[1] "Unmatch Case # 4953"
[1] "Question: +200984144411 * -3395871955557"
[1] "Native Multiplication: -682516419516933058068480 | infiX: -682516419516933061941927"
[1] ""
[1] "Case #4953 +302644987703 * -2613759914367"
[1] "Unmatch Case # 4954"
[1] "Question: +302644987703 * -2613759914367"
[1] "Native Multiplication: -791041337142195081183232 | infiX: -791041337142195048029001"
[1] ""
[1] "Case #4954 +297710951409 * -7389205776072"
[1] "Unmatch Case # 4955"
[1] "Question: +297710951409 * -7389205776072"
[1] "Native Multiplication: -2199847481751273310519296 | infiX: -2199847481751273326885448"
[1] ""
[1] "Case #4955 +196729427817 * -3341342364643"
[1] "Unmatch Case # 4956"
[1] "Question: +196729427817 * -3341342364643"
[1] "Native Multiplication: -657340371536919144693760 | infiX: -657340371536919161474331"
[1] ""
[1] "Case #4956 +750274970827 * -6082396235238"
[1] "Unmatch Case # 4957"
[1] "Question: +750274970827 * -6082396235238"
[1] "Native Multiplication: -4563469657951445155053568 | infiX: -4563469657951445079401826"
[1] ""
[1] "Case #4957 +269232490453 * -8822101960162"
[1] "Unmatch Case # 4958"
[1] "Question: +269232490453 * -8822101960162"
[1] "Native Multiplication: -2375196481764708191305728 | infiX: -2375196481764708251333386"
[1] ""
[1] "Case #4958 +67452015067 * -7095018896304"
[1] "Unmatch Case # 4959"
[1] "Question: +67452015067 * -7095018896304"
[1] "Native Multiplication: -478573321494147085893632 | infiX: -478573321494147118612368"
[1] ""
[1] "Case #4959 +928567913097 * -35667352043"
[1] "Unmatch Case # 4960"
[1] "Question: +928567913097 * -35667352043"
[1] "Native Multiplication: -33119558652264527691776 | infiX: -33119558652264529407171"
[1] ""
[1] "Case #4960 +84308532583 * -2544110976949"
[1] "Unmatch Case # 4961"
[1] "Question: +84308532583 * -2544110976949"
[1] "Native Multiplication: -214490263194872714362880 | infiX: -214490263194872728429267"
[1] ""
[1] "Case #4961 +942319158109 * -2806338263229"
[1] "Unmatch Case # 4962"
[1] "Question: +942319158109 * -2806338263229"
[1] "Native Multiplication: -2644466309575024647864320 | infiX: -2644466309575024511873961"
[1] ""
[1] "Case #4962 +67691621895 * -412258262918"
[1] "Unmatch Case # 4963"
[1] "Question: +67691621895 * -412258262918"
[1] "Native Multiplication: -27906430456534753345536 | infiX: -27906430456534755389610"
[1] ""
[1] "Case #4963 +333816645833 * -8571583459"
[1] "Unmatch Case # 4964"
[1] "Question: +333816645833 * -8571583459"
[1] "Native Multiplication: -2861337239761004265472 | infiX: -2861337239761004076347"
[1] ""
[1] "Case #4964 +314951466443 * -1975604700203"
[1] "Unmatch Case # 4965"
[1] "Question: +314951466443 * -1975604700203"
[1] "Native Multiplication: -622219597440618174873600 | infiX: -622219597440618229787929"
[1] ""
[1] "Case #4965 +29318486201 * -3302131458448"
[1] "Unmatch Case # 4966"
[1] "Question: +29318486201 * -3302131458448"
[1] "Native Multiplication: -96813495598395691106304 | infiX: -96813495598395692876048"
[1] ""
[1] "Case #4966 +699993178739 * -8156539618684"
[1] "Unmatch Case # 4967"
[1] "Question: +699993178739 * -8156539618684"
[1] "Native Multiplication: -5709522095193204042235904 | infiX: -5709522095193204115959476"
[1] ""
[1] "Case #4967 +523767467430 * -5343792355076"
[1] "Unmatch Case # 4968"
[1] "Question: +523767467430 * -5343792355076"
[1] "Native Multiplication: -2798904588289952003915776 | infiX: -2798904588289951825174680"
[1] ""
[1] "Case #4968 +867061047538 * -9432345348310"
[1] "Unmatch Case # 4969"
[1] "Question: +867061047538 * -9432345348310"
[1] "Native Multiplication: -8178419238445849876889600 | infiX: -8178419238445850077960780"
[1] ""
[1] "Case #4969 +760844132947 * -7321467429909"
[1] "Unmatch Case # 4970"
[1] "Question: +760844132947 * -7321467429909"
[1] "Native Multiplication: -5570495538608813614563328 | infiX: -5570495538608813600111823"
[1] ""
[1] "Case #4970 +795850353082 * -6540742939409"
[1] "Unmatch Case # 4971"
[1] "Question: +795850353082 * -6540742939409"
[1] "Native Multiplication: -5205452577747250840600576 | infiX: -5205452577747251182408538"
[1] ""
[1] "Case #4971 +654940610909 * -308737519486"
[1] "Unmatch Case # 4972"
[1] "Question: +654940610909 * -308737519486"
[1] "Native Multiplication: -202204739622690147532800 | infiX: -202204739622690131672774"
[1] ""
[1] "Case #4972 +890134661063 * -1265037102246"
[1] "Unmatch Case # 4973"
[1] "Question: +890134661063 * -1265037102246"
[1] "Native Multiplication: -1126053372239862852222976 | infiX: -1126053372239862886047498"
[1] ""
[1] "Case #4973 +829044278631 * -7662062632044"
[1] "Unmatch Case # 4974"
[1] "Question: +829044278631 * -7662062632044"
[1] "Native Multiplication: -6352189187608459094261760 | infiX: -6352189187608459165051764"
[1] ""
[1] "Case #4974 +246970548148 * -8238800159868"
[1] "Unmatch Case # 4975"
[1] "Question: +246970548148 * -8238800159868"
[1] "Native Multiplication: -2034740991564429893042176 | infiX: -2034740991564429991324464"
[1] ""
[1] "Case #4975 +33114936616 * -721461888379"
[1] "Unmatch Case # 4976"
[1] "Question: +33114936616 * -721461888379"
[1] "Native Multiplication: -23891164704530252169216 | infiX: -23891164704530251985464"
[1] ""
[1] "Case #4976 +861978173295 * -8012396424769"
[1] "Unmatch Case # 4977"
[1] "Question: +861978173295 * -8012396424769"
[1] "Native Multiplication: -6906510833937771558600704 | infiX: -6906510833937771512343855"
[1] ""
[1] "Case #4977 +873888120127 * -2422441529079"
[1] "Unmatch Case # 4978"
[1] "Question: +873888120127 * -2422441529079"
[1] "Native Multiplication: -2116942873964422602162176 | infiX: -2116942873964422715673033"
[1] ""
[1] "Case #4978 +271115865040 * -3132227571720"
[1] "Unmatch Case # 4979"
[1] "Question: +271115865040 * -3132227571720"
[1] "Native Multiplication: -849196587609006425505792 | infiX: -849196587609006440668800"
[1] ""
[1] "Case #4979 +374399613864 * -6583614537522"
[1] "Unmatch Case # 4980"
[1] "Question: +374399613864 * -6583614537522"
[1] "Native Multiplication: -2464902740677653562392576 | infiX: -2464902740677653739405008"
[1] ""
[1] "Case #4980 +9681130196 * -3412651225136"
[1] "Unmatch Case # 4981"
[1] "Question: +9681130196 * -3412651225136"
[1] "Native Multiplication: -33038320824080524115968 | infiX: -33038320824080523806656"
[1] ""
[1] "Case #4981 +473118225703 * -6155847804393"
[1] "Unmatch Case # 4982"
[1] "Question: +473118225703 * -6155847804393"
[1] "Native Multiplication: -2912443790912124308422656 | infiX: -2912443790912124368913279"
[1] ""
[1] "Case #4982 +2581446693 * -4194331420517"
[1] "Unmatch Case # 4983"
[1] "Question: +2581446693 * -4194331420517"
[1] "Native Multiplication: -10827442974839602675712 | infiX: -10827442974839602000281"
[1] ""
[1] "Case #4983 +588416040951 * -6667539579035"
[1] "Unmatch Case # 4984"
[1] "Question: +588416040951 * -6667539579035"
[1] "Native Multiplication: -3923287241979871725879296 | infiX: -3923287241979871861062285"
[1] ""
[1] "Case #4984 +539734249551 * -9575815420226"
[1] "Unmatch Case # 4985"
[1] "Question: +539734249551 * -9575815420226"
[1] "Native Multiplication: -5168395549674573418987520 | infiX: -5168395549674573816818526"
[1] ""
[1] "Case #4985 +753691845168 * -4298053351646"
[1] "Unmatch Case # 4986"
[1] "Question: +753691845168 * -4298053351646"
[1] "Native Multiplication: -3239407761232580323573760 | infiX: -3239407761232580489946528"
[1] ""
[1] "Case #4986 +485861519460 * -1245858295995"
[1] "Unmatch Case # 4987"
[1] "Question: +485861519460 * -1245858295995"
[1] "Native Multiplication: -605314604723977184083968 | infiX: -605314604723977132562700"
[1] ""
[1] "Case #4987 +26009719697 * -421574487916"
[1] "Unmatch Case # 4988"
[1] "Question: +26009719697 * -421574487916"
[1] "Native Multiplication: -10965034262101472837632 | infiX: -10965034262101473681452"
[1] ""
[1] "Case #4988 +485269967062 * -3328710695062"
[1] "Unmatch Case # 4989"
[1] "Question: +485269967062 * -3328710695062"
[1] "Native Multiplication: -1615323329351663975661568 | infiX: -1615323329351663866047844"
[1] ""
[1] "Case #4989 +312284565862 * -7570883180089"
[1] "Unmatch Case # 4990"
[1] "Question: +312284565862 * -7570883180089"
[1] "Native Multiplication: -2364269967086011361001472 | infiX: -2364269967086011327521718"
[1] ""
[1] "Case #4990 +785414799604 * -59390447066"
[1] "Unmatch Case # 4991"
[1] "Question: +785414799604 * -59390447066"
[1] "Native Multiplication: -46646136080734361747456 | infiX: -46646136080734359761864"
[1] ""
[1] "Case #4991 +382009516086 * -999053556576"
[1] "Unmatch Case # 4992"
[1] "Question: +382009516086 * -999053556576"
[1] "Native Multiplication: -381647965691594993041408 | infiX: -381647965691594983081536"
[1] ""
[1] "Case #4992 +693594577772 * -3329078301745"
[1] "Unmatch Case # 4993"
[1] "Question: +693594577772 * -3329078301745"
[1] "Native Multiplication: -2309030659068750047739904 | infiX: -2309030659068750085812140"
[1] ""
[1] "Case #4993 +532756670312 * -683690580956"
[1] "Unmatch Case # 4994"
[1] "Question: +532756670312 * -683690580956"
[1] "Native Multiplication: -364240717433795434774528 | infiX: -364240717433795437778272"
[1] ""
[1] "Case #4994 +468136190363 * -4684898951986"
[1] "Unmatch Case # 4995"
[1] "Question: +468136190363 * -4684898951986"
[1] "Native Multiplication: -2193170747618337310638080 | infiX: -2193170747618337292910918"
[1] ""
[1] "Case #4995 +81252317553 * -5201267321788"
[1] "Unmatch Case # 4996"
[1] "Question: +81252317553 * -5201267321788"
[1] "Native Multiplication: -422615024107960385142784 | infiX: -422615024107960411744764"
[1] ""
[1] "Case #4996 +744694876972 * -2843195573272"
[1] "Unmatch Case # 4997"
[1] "Question: +744694876972 * -2843195573272"
[1] "Native Multiplication: -2117313177645127045218304 | infiX: -2117313177645127051492384"
[1] ""
[1] "Case #4997 +827632827549 * -4000711103499"
[1] "Unmatch Case # 4998"
[1] "Question: +827632827549 * -4000711103499"
[1] "Native Multiplication: -3311119842795557400608768 | infiX: -3311119842795557357493951"
[1] ""
[1] "Case #4998 +37251467619 * -6742800568476"
[1] "Unmatch Case # 4999"
[1] "Question: +37251467619 * -6742800568476"
[1] "Native Multiplication: -251179217037958517358592 | infiX: -251179217037958506178644"
[1] ""
[1] "Case #4999 +611549762887 * -1720166280402"
[1] "Unmatch Case # 5000"
[1] "Question: +611549762887 * -1720166280402"
[1] "Native Multiplication: -1051967280906055853277184 | infiX: -1051967280906055855040574"
[1] ""
[1] "Case #5000 +646429567671 * -4434748517726"
[1] "Unmatch Case # 5001"
[1] "Question: +646429567671 * -4434748517726"
[1] "Native Multiplication: -2866752567043226083524608 | infiX: -2866752567043226260036146"

Begin of Chapter 3

In the previous two chapters of infinity multiplication for R Programming Language, 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’s 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 CalculationNext 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. For this version of infiX() that built for R, I only did the test result of 1,000 cases for the benchmark test.

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 1,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 R took 15.039 seconds to compute the results for 1,000 cases. For each case the same two strings of numbers were used, each string of number contained forty digits and did not contain the decimal. With the decimal, the program took 15.558 seconds to compute the results. To compare this to the previous version, the previous version took 155.338 seconds to compute the results for 1,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 164.339 seconds to execute.

How did I make the program run more than ten times faster? Instead of processing one digit at a time, I converted the program into processing five digits at a time. 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 five digits at a time, we would still use the same procedures for each multiplication cycle. However, the procedures are now applied to five 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.

Besides the procedures, I found out that R’s for loop execute 10x faster than the while loop. R’s for loop is a bit inflexible to use, but I found a method that can make the for loop as flexible as possible. The for loop took around 500 milliseconds to execute ten million empty cycles. The while loop took about six seconds for the same ten million cycle.

For converting the strings with digits into integer format, I used the as.numeric() function instead of strtoi(), as.numeric() was benchmarked to run faster than strtoi() function. For grabbing the digits from the string, I used the substr() function instead of the substring() function due to the speed of execution.

The reason why I only calculate five digits at a time is due to the fact that the maximum value a 32 bits block integer can hold is 2,147,483,647. Which in term are about 12 digits. Nevertheless, the amount of digit the program can work with at a time can be set to seven digits. The program will execute faster. Also, the as.numeric() function was producing errors when calculating an eight digits number multiply by another eight digits number. Thus with my test result, in my opinion, five digits at a time is the safe range for now. However, I also tested the infiX with seven digits at a time and did not found any errors, the seven digits at a time test was not as thoroughly as the one to five digits at a time.

For a multiplication equation, five digits multiply by another five digits have the potential to produce the maximum value that is ten digits. This is well below the maximum value that a 32 bits block integer can hold. If I was to compute six digits at a time I have the potential to produce a result with the maximum value of 9,999,980,00,001. This can overflow the memory of what a 32 bits block integer can hold and produce an incorrect result.

The formula for multiplying five digits at a time is similar to multiplying one digit at a time. Nevertheless writing the result to the output string can be a very complex task without a temporary answer string. Let’s first look at the example.

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 example 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 is a six digits value we would also keep the five first digits from the right and keep the left most digit 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, 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.

Besides the index for reading, we would also need a variable for calculating which position we are working on in our answer string. The third new variable is the negdigit variable. This is just the amount of digits we are working with in negative value. This variable is needed because when we are stepping backward in the for loop, we have to initialise a seq() function, the negative value is use for how many steps we are stepping after each loop. Since we are reading five digits at a time and we are reading from the end of the string, we would use the string’s length as our starting sequence for the for loop. The loop will execute until we reach one or before we reach one if the next step is going to be below one. For each loop we want the index to be minus by five for the purpose of this article.

The other variable we need is the pad0 variable. Since we are multiplying five digits at a time, we would only want to store five digits at a time. Thus if the result from a block of digits in A string multiply by a block of digits in B string happen to produce less than fives digit we have to pad zero to the beginning of the current result. This will be explained further down below.

After variable declaration, we would produce a string of zeroes bases on how many digits we wanted to work with at a time. If we are working with five digits at a time, we would want to produce a padding string of four zeroes for the event where our result have less than five digits. This will be explained further down.

temp <- 0;
alen <- nchar(a);
blen <- nchar(b);
posr <- 0;
posw <- 0;
digit <- 5;
negdigit <- digit * - 1
pad0 <- "";

for (i in seq(1,digit - 1,1) ){
    pad0 <- paste("0", pad0, sep="") 
}

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

To get five digits from B string, I used the substr() function. The syntax of this function is, substr(string_variable_or_string, argument_1, argument_2). For this function, argument one and two accepts integer value as input. These two positions that are defined by the first and the second argument are calls the position “start” and “stop”. The “start” position is defines by the first argument and the “stop” position is defines by the second argument.

As the time of this writing, R counts the “start” and the “stop” position from left to right. For example, if the “stop” position is before the “start” position from left to right, R would return an empty string. Another behavior from the substr() function is that, if the “stop” position is larger than the string length or is after the last position on the string counting from the left, R will return all the characters from the “start” position to the end of the string. R’s substr() function will grab the digits that located in the “start” position and also in the “stop” position. Another behavior to the substr() function is that, if the first argument is a negative value, R will treat that as the first position in the string from left to right. Zero and one would also be treated as the first position in the string for the substr() function first argument.

To get five digits from B string, we can use the substr() function. The first position we inputted into the substr() function is the start position, which is the current position we are at minus the amount of digit we want to work with plus one. The reason why we would have to add one can be demonstrated by a short example. For example, if we are on position twenty of the string and we wanted to grab five digits from the string before the position where we are at including the position where we are at. We are actually grabbing digits in position 16,17,18,19 and 20. If we use twenty and minus to five we would also get the digits in position 15, which would not be the intended digit we wanted to grab. The value for the stop position would be the current position where we are at in B string. The method for grabbing a digit from A string is similar to the method of grabbing a digit 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 use the substr() function and get the digits from the first position to five positions away from the end of the string. This value is then converted to an integer type with the as.numeric() function. If the leftover variable does not contain any digits, the as.numeric() function will produce an NA value. Therefore we would use is.na() function to check if the leftover variable contained an NA result. If the leftover contains an NA result we would assign a zero value to the leftover variable.

When appending the result to the answer string, we want to always append the digits in the format of five digits. Therefore we would have to append to the result zeroes in the event where the block of digits is less than five digits. The reason why is when 1 00125 x 1 00001, 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 five digits for all the result, we would add four zeroes to the beginning of the result value. We then use the substr() function to grab the amount of digit that we wanted to worked with which was five for this article from the right side of the temp string. We can input the temp string’s length minus to the amount of digit we wanted to work with and the plus one as the first argument of the substr() function. The temp string’s length is used as the second argument.

After multiplying all the digits block in A string to the first block of digits in B string, we would append any leftover value to the leftmost of the answer string. The principle of a consistent amount of digits in a block of digits would also apply to this procedure.

This code block below demonstrate the mentioned procedures in R.

  for ( bi in seq(blen, 1, negdigit )){ 
    z <- as.numeric(substr(b, bi - digit + 1 , bi));
    outlen <- nchar(output);
    leftover <- 0;
    if ( outlen < 1 ){
      for ( ai in seq(alen,1, negdigit )){
        temp <- toString( as.numeric(substr(a, ai - digit + 1, ai)) * z + leftover);
        leftover <- strtoi(substr(temp,1, nchar(temp) - digit));
        leftover <- ifelse( is.na(leftover), 0, leftover);
        temp <- paste(pad0, temp, sep="");
        output <- paste( substr(temp, nchar(temp) - digit + 1, nchar(temp)), output, sep="");
      }
      if ( leftover > 0 ){
        leftover <- paste(pad0, toString(leftover), sep="");
        output <- paste( substr(leftover, nchar(leftover) - digit + 1, nchar(leftover)), output, sep="");
      }
    }

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 digits block in A string, we would have to calculate the position where we are working with in our answer string. The starting position for the answer string would move over from the right to the left for each digits block we read in B string. Besides that, the position that we are working with in the answer string would 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 digit we wanted to work with and add this value to the first value. The programming code can be simplified to, how many times we read in A string plus how many times we read from B string then multiply by the amount of digit the program was set 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. This value is stored in a temporary variable name tempadd. To get the digits in the answer string, we use the answer string current length minus the position we are currently in minus the amount of digit the program was set to work with plus one as the start position for the substr() function. For the stop position, we simply minus the answer string current length to the position we are currently working with. If we are working in the position that is beyond the first position in the answer string we would not get any digit and therefore we have to check for an NA result to assign zero when necessary.

If the tempadd variable holds a value that is larger than five digits in length we would produce a remainder. The method for producing the remainder is similar to producing the leftover.

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. We then add our tempadd value to the right side of this string and then add the rest the digits from after the last digit we grabbed from the answer string to the end of the answer string. Notice that if our posw position is before the first position in our answer string we would not add an empty value before the tempadd variable. The reason for this is because we are moving the starting position in the answer string to the left with each new multiplication cycle, and we will eventually write to the position that is before the beginning 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 R.

for ( ai in seq(alen,1, negdigit )){
        posw <- (posr + loopidx) * digit;
        temp <- toString( as.numeric(substr(a, ai - digit + 1, ai)) * z + leftover + remainder);
        templen <- nchar(temp);
        
        leftover <- as.numeric(substr(temp,1, templen - digit));
        leftover <- ifelse( is.na(leftover),0,leftover);
        
        outposval <- as.numeric(substr(output,(outlen - (posw + digit) + 1), outlen - posw));
        outposval <- ifelse( is.na(outposval), 0, outposval);
        
        tempadd <- toString( as.numeric(substr(temp, ifelse(templen - digit + 1 > 1, templen - digit + 1, 1) , templen)) + outposval); 
        
        remainder <- as.numeric(substr(tempadd,1, nchar(tempadd) - digit));
        remainder <- ifelse( is.na(remainder), 0, remainder);
        
        tempadd <- paste(pad0, substr(tempadd, nchar(tempadd) - digit + 1, nchar(tempadd)), sep="");
        
        
        outlen <- nchar(output);
        output <- paste( ifelse(outlen - posw + digit + 1 < 1 , "", substr(output,1, outlen - (posw + digit))) , 
                         substr(tempadd, nchar(tempadd) - digit + 1, nchar(tempadd)) , 
                         substr(output, ifelse(outlen - posw + 1 > 1, outlen - posw + 1, 1), outlen ), 
                         sep="");
        loopidx <- loopidx + 1
      }
      if ( remainder + leftover > 0 ){
        leftover <- paste(pad0, toString(leftover + remainder), sep="");
        output <- paste( substr(leftover, (nchar(leftover) - digit + 1), nchar(leftover)), output, sep="");
 
      }

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 R’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 given by infiX and the result given by native multiplication function.

To use this tester, simply look for version two of infiX which is called “Decimal, Precise Float Calculation” and pair this tester code into the program. This code below is the tester cases. I preset the amount of run to 1000 cases, this can be increased. For R, it is safe to set the amount of case to run at less than or equal to 5,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.

um <- 0;
m <- 0;
options(scipen = 999)
for (id in 0:1000 ){
  a1 <- floor(runif(1, min=1, max=999));
  ac1 <- floor(runif(1, min=0, max=99));
  
  b1 <- floor(runif(1, min=1, max=999)); 
  bc1 <- floor(runif(1, min=0, max=99));
  padA <- "";
  padB <- "";
  idn <- 0;
  idn2 <- 0;
  
  while ( idn < floor(runif(1, min=0, max=0)) ){
    idn <- idn + 1;
    padA <- paste("0", padA , sep="");
  }
  
  while ( idn2 < floor(runif(1, min=0, max=0)) ){
    idn2 <- idn2 + 1;
    padB <- paste("0", padB, sep="");
  }
  
  ta <- paste("+", toString(a1),padA,toString(ac1) ,sep="") ;
  tb <- paste("-", toString(b1),padB,toString(bc1) ,sep="")  ;
  ta <- ta;
  tb <- tb;
  
  
  test1 <- as.numeric(ta) * as.numeric(tb);
  test2 <- infiX(ta, tb );
  test1 <- toString(test1);
  
  print (paste("Case #", toString(id), " ", toString(ta), " * ", toString(tb), sep=""));
  if ( test1 != test2  ){
    um <- um + 1;
    print( paste("Unmatch Case #", toString(um)),sep="");
    print( paste("Question: " ,toString(ta), " * ", toString(tb), sep="")   );
    print( paste("Native Multiplication: " ,toString(test1), " | infiX: ", toString(test2), sep=""));
    print("");
  } 
  if ( test1 == test2  ){
    m <- m + 1;
  } 
}
print( paste("Unmatch ", toString(um), " cases.", sep=""));
print( paste("Match ", toString(m), " cases.", sep=""));

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 testing 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 three blocks of random numbers in front of the decimal for each string. The random blocks of numbers can be anywhere between one to ten digits. The tester will then pad 0 to 15 zeroes behind the decimal and then two blocks of random numbers before adding another 0 to 15 zeroes and then the last one blocks of random digits. As recommended, this tester should not be set to execute above 10000 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 R.

options(scipen = 12)
um <- 0;
m <- 0;
for (id in 1:2000 ){
  a1 <- toString(floor(runif(1, min=1, max=9999999999)));
  a2 <- toString(floor(runif(1, min=1, max=9999999999)));
  a3 <- toString(floor(runif(1, min=1, max=9999999999)));
  ac1 <- toString(floor(runif(1, min=1, max=9999999999)));
  ac2 <- toString(floor(runif(1, min=1, max=9999999999)));
  ac3 <- toString(floor(runif(1, min=1, max=9999999999)));
  
  
  b1 <- toString(floor(runif(1, min=1, max=9999999999)));
  b2 <- toString(floor(runif(1, min=1, max=9999999999)));
  b3 <- toString(floor(runif(1, min=1, max=9999999999)));
  bc1 <- toString(floor(runif(1, min=1, max=9999999999)));
  bc2 <- toString(floor(runif(1, min=1, max=9999999999)));
  bc3 <- toString(floor(runif(1, min=1, max=9999999999)));
  padA1 <- "";
  padA2 <- "";
  padB1 <- "";
  padB2 <- "";
  idn <- 0;
  idn2 <- 0;
  
  while ( idn < floor(runif(1, min=0, max=15)) ){
    idn <- idn + 1;
    padA1 <- paste("0", padA1 , sep="");
  }
  
  while ( idn2 < floor(runif(1, min=0, max=15)) ){
    idn2 <- idn2 + 1;
    padB1 <- paste("0", padB1, sep="");
  }
  while ( idn < floor(runif(1, min=15, max=30)) ){
    idn <- idn + 1;
    padA2 <- paste("0", padA1, sep="");
  }
  
  while ( idn2 < floor(runif(1, min=15, max=30)) ){
    idn2 <- idn2 + 1;
    padB2 <- paste("0", padB1, sep="");
  }
  
  
  ta <- paste("+", a1, a2, a3, ".", padA1, ac1, ac2, padA2, ac3 ,sep="") ;
  tb <- paste("-", b1, b2, b3, ".", padB1, bc1, bc2, padB2, bc3 ,sep="")  ;
  
  test1 <- infiX(ta, tb);
  test2 <- infiX2(ta, tb);
  
  print (paste("Case #", toString(id), " : ", ta, " * ", tb, sep=""));
  if ( test1 != test2  ){
    um <- um + 1;
    print( paste("Unmatch Case #", toString(um)),sep="");
    print( paste("Question: " ,ta, " * ", tb, sep="")   );
    print( paste("Infi X3:" ,test1, " | infiX2: ", toString(test2), sep=""));
    print("");
  } 
  if ( test1 == test2  ){
    m <- m + 1;
  } 
}
print( paste("Unmatch ", toString(um), " cases.", sep=""));
print( paste("Match ", toString(m), " cases.", sep=""));

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 is 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 R Programming Language and is designed for a production environmen.
#         The first limitation of this version is how much memory R Programming Language allow the string to be store.
#         The second limitation is how much memory R'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 costed 500MB per string.


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, it will treat both position as position one.
  # This is from the left side of the string.
  options(scipen = 12)
  
  searchPos <- function(match, string){
    found <- -1
    for ( i in 1:nchar(string)){
      if ( substr(string,i,i) == match ){
        found <- i;
        break;
      }
    }
    return(found);
  }
  
  
  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 ( 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 ( 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;
  alen <- nchar(a);
  blen <- nchar(b);
  output <- "";
  posr <- 0;
  posw <- 0;
  digit <- 5; # Do not change this to above 7, as.numeric will produce error result and this function will also produce incorrect answer. This function is tested throughly from 1 - 7 digits.
  # Change this to beyond 5 is your own risk. Above 7 it is a gurantee that will not get the correct format with the current version of R at this time of writting.
  negdigit <- digit * - 1
  pad0 <- "";
  
  for (i in seq(1,digit - 1,1) ){
    pad0 <- paste("0", pad0, sep="")
  }
  for ( bi in seq(blen, 1, negdigit )){ 
    z <- as.numeric(substr(b, bi - digit + 1 , bi));
    outlen <- nchar(output);
    leftover <- 0;
    if ( outlen < 1 ){
      for ( ai in seq(alen,1, negdigit )){
        temp <- toString( as.numeric(substr(a, ai - digit + 1, ai)) * z + leftover);
        leftover <- strtoi(substr(temp,1, nchar(temp) - digit));
        leftover <- ifelse( is.na(leftover), 0, leftover);
        temp <- paste(pad0, temp, sep="");
        output <- paste( substr(temp, nchar(temp) - digit + 1, nchar(temp)), output, sep="");
      }
      if ( leftover > 0 ){
        leftover <- paste(pad0, toString(leftover), sep="");
        output <- paste( substr(leftover, nchar(leftover) - digit + 1, nchar(leftover)), output, sep="");
      }
    } else {
      remainder <- 0;
      tempadd <- 0;
      loopidx <- 0;
      for ( ai in seq(alen,1, negdigit )){
        posw <- (posr + loopidx) * digit;
        temp <- toString( as.numeric(substr(a, ai - digit + 1, ai)) * z + leftover + remainder);
        templen <- nchar(temp);
        
        leftover <- as.numeric(substr(temp,1, templen - digit));
        leftover <- ifelse( is.na(leftover),0,leftover);
        
        outposval <- as.numeric(substr(output,(outlen - (posw + digit) + 1), outlen - posw));
        outposval <- ifelse( is.na(outposval), 0, outposval);
        
        tempadd <- toString( as.numeric(substr(temp, ifelse(templen - digit + 1 > 1, templen - digit + 1, 1) , templen)) + outposval); 
        
        remainder <- as.numeric(substr(tempadd,1, nchar(tempadd) - digit));
        remainder <- ifelse( is.na(remainder), 0, remainder);
        
        tempadd <- paste(pad0, substr(tempadd, nchar(tempadd) - digit + 1, nchar(tempadd)), sep="");
        
        
        outlen <- nchar(output);
        output <- paste( ifelse(outlen - posw + digit + 1 < 1 , "", substr(output,1, outlen - (posw + digit))) , 
                         substr(tempadd, nchar(tempadd) - digit + 1, nchar(tempadd)) , 
                         substr(output, ifelse(outlen - posw + 1 > 1, outlen - posw + 1, 1), outlen ), 
                         sep="");
        loopidx <- loopidx + 1
      }
      if ( remainder + leftover > 0 ){
        leftover <- paste(pad0, toString(leftover + remainder), sep="");
        output <- paste( substr(leftover, (nchar(leftover) - digit + 1), nchar(leftover)), output, sep="");
        
      }
    }
    posr <- posr + 1
  }
  
  if ( oDecPos > 0 ){
    while ( nchar(output) < oDecPos){
      output = paste("0",output, sep="");
    }    
    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);
    return (ifelse(isaNeg != isbNeg, paste("-", output, sep="") , output ));
  } 
  output <- gsub("^0+", "", output);
  return (ifelse(isaNeg != isbNeg, paste("-", output, sep="") , output ));    
  
}

x = "-11111111111111111111111111111111111111111111111111111111111111111111112222222222222222222222222";
y = "-99999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999999";
c = infiX(x,y);
print(c);

Digiprove sealCopyright secured by Digiprove © 2017

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 – R".
Original Post Link: http://kevinhng86.iblog.website/2017/02/21/working-with-number-infinity-multiplication-optimised-the-code-r/.

Advertisement


Random Article You May Like

Leave a Reply

Your email address will not be published. Required fields are marked *

*
*