# Sum of numbers of arbitrary length

Your function must accept 2 strings which are correct numbers. It needs to sum them up (without rounding and floating point errors) and return the result (which is also a correct number) without any leading zeros in the integer part, trailing zeros in the decimal part and without minus if the answer is 0 i.e. -0 is not allowed.

A correct number is a string which can start with a leading minus, contains only digits and can contain only one dot which will be between the digits:

'1234567890'
'-1234567890'
'12345.67890'
'-12345.67890'


In other words, it matches the regex -?\d+(\.\d+)?

Your input will always be valid so you don't need to think about empty strings, etc.

The input strings can be as large as possible in your programming language, but it is guaranteed that the length of the resulting string will not be larger than what is available in your programming language.

### Some test cases:

'1', '1' --> '2'
'0', '0' --> '0'
'9', '1' --> '10'
'001.002', '3.400' --> '4.402'
'5', '-5.0' --> '0'
'2', '-2.5' --> '-0.5'
'12345', '67890' --> '80235'
'-50.6', '20.53' --> '-30.07'
'-001.00', '00100' --> '99'
'-00.100', '-0.20' --> '-0.3'
'0.1', '0.2' --> '0.3'
'1000000000000', '-0.000000000001' --> '999999999999.999999999999'


The shortest code in each programming language wins!

• How I must understand what is not clear for you? It is better to write a comment than just voting to close and I will add additional information Feb 6 at 9:15
• @JosWoolley If in Excel you can do it simply than it is not a problem :) A lot of programming languages can't work properly with any decimal number, so if you don't have any issues with this problem in your language then it is great and you can write an answer with test cases Feb 6 at 9:28
• I don't see how this question Needs Details or Clarity. It's probably been done before, so if anyone who wants this closed can go through the effort to find a dupe target, fair game, but it seems perfectly clear what the task is. Feb 6 at 14:17
• @EzioMercer most regex syntax is identical across languages. the one I added would be exactly the same in absolutely any language (assuming the backslashes are properly escaped) Feb 6 at 17:48
• The issue with this challenge is that it is essentially a chameleon challenge. While the title says that the goal is to "Sum numbers which are strings", the real challenge is to do so without any precision issues from floats or any rounding issues, leading to a lot of invalid answers only looking at the first part
– Jo King
Feb 8 at 1:37

# Java 8, 103 102 bytes

import java.math.*;a->b->new BigDecimal(a).add(new BigDecimal(b)).stripTrailingZeros().toPlainString()


Try it online.

Explanation:

import java.math.*;        // Required import for BigDecimal
a->b->                     // Method with String as two parameters & return-type
new BigDecimal(a)        //  Convert the first input to a BigDecimal
new BigDecimal(b)) //   The second input as BigDecimal
.stripTrailingZeros()    //  Remove any no-op trailing 0s
.toPlainString()         //  Convert and return it as plain String (so no scientific
//  notation)

• Those builtin names are so long though...
– Neil
Feb 6 at 12:47
• @Neil ikr.. Java is verbose as fwck.. :/ I've looked in the source code of both those methods to see what they do, but unfortunately it can't really be shortened manually. And java.math.BigDecimal is verbose to begin with.. Feb 6 at 13:07
• I don't know Java, so just out of interest: can't you save a few bytes if you store new java.math.BigDecimal in a variable like d and then just call d(a) and/or  d(b)? Feb 6 at 14:39
• @EzioMercer Unfortunately no. Java can't really save methods in variables, unless they're lambdas. In addition, new java.math.BigDecimal(String) is a constructor instead of a method. There also isn't a java.math.BigDecimal.valueOf(String) method; valueOf only accepts numeric argument-types. Although even if there was such a method, the lambda would require a body with return, so a->b->{java.math.BigDecimal T=null;return T.valueOf(a).add(T.valueOf(b)).stripTrailingZeros().toPlainString();} would still be 8 bytes longer. Feb 6 at 14:48
• Thank you for detailed explanation! Feb 6 at 14:52

$~*+*o**.FatRat  Try it online! This converts both arguments to FatRats (arbitrary sized bignums), before adding them together and stringifying the result. You could remove the o**.FatRat part, but this would use Rats, which decay to floating point numbers once the precision needed is too high. • With use 6.e.PREVIEW; one can write $*RAT-OVERFLOW = FatRat; to obviate the need for the o**.FatRat part in the dynamic scope of such a statement. (Maybe it would be worth discussing the pros and cons of switching to $*RAT-OVERFLOW = FatRat as the default for 6.e?) Also, I don't know if there's a convenient way to add such a statement to a SETTING for execution of the raku binary but that would make it particularly nice. (If there isn't, maybe it would be worth discussing that too.) Feb 16 at 17:22 • It took me a while to understand the Footer code in your tio. For the record I wrote this alternative: { say "'$0', '$1' --> '$2'" => f $0,$1 with $/ = .comb: / \' <(.*?)> \' / } for lines. Feb 16 at 17:24 # Fig, $$\5\log_{256}(96)\approx\$$ 4.116 bytes B+_x_  Try it online! Since Fig uses BigDecimals, this doesn't suffer from floating point issues as some other answers do. B+_x_ _ # Convert first input to number _x # Convert second input to number + # Add B # Convert to string  • You're expected to remove trailing zeros after the ., even when those were included in the inputs. – Neil Feb 7 at 10:23 • @Neil does it not? Feb 7 at 14:43 • If I put in "0.44" and "0.56" as inputs then the displayed result is 1.00 but I think it's only supposed to display 1. And then there are some of the test cases such as '-001.00', '00100' --> '99'. – Neil Feb 7 at 17:21 • Hrm that would be a bug in Fig. Printing should always remove trailing zeros Feb 7 at 18:51 # Python, 84 bytes lambda*x:(s:=str(sum(map(Decimal,x))))[-2:]=='.0'and s[:-2]or s from decimal import*  Attempt This Online! Normal numbers succumb to floating point inaccuracies, so we need to convert to decimal.Decimal. • There does seem to be an issue of the output size being limited, e.g add a few more zeroes to the 0.00..001 case and it will round it up. I don't know how one would fix this – Jo King Feb 7 at 21:36 # bash, + bc, 30 bytes bc<<<$1+$2|sed -r "s/\.*0+$//"


Try it online!

## How?

This takes advantage of bc being an arbitrary precision calculator language. It pipes the input (expected to be two arguments) to bc which adds them.

10 bytes to do the calculation, bc<<<$1+$2. 20 bytes to pipe to sed and remove trailing zeroes.

The golf-y bit is replacing echo with the bash here string (<<<), as in this tip. The code is the equivalent of echo $1+$2 | bc. This is my first attempt at a challenge in a language other than R. I would be interested in tips to golf further.

Try it online!

## Example output

I am not exactly sure how to provide a list of string test cases on TIO. In the absence of that, here is the example output for the final test case on my machine (script is called calc.sh):

$./calc.sh '1000000000000' '-0.000000000001' 999999999999.999999999999  $ ./calc.sh '-00.100' '-0.20'
-.3


## bash + bc, 31 bytes

This did not strip all trailing zeroes, as pointed out in the comments by @roblogic.

m=bc<<<$1+$2
echo ${m//[0$]/}


Try it online!

## Answer which did not meet spec, 10 bytes

bc<<<$1+$2


Unfortunately, as pointed out by
Ismael Miguel in the comments, the question says to

return the result (which is also a correct number) without any leading zeros in the integer part, trailing zeros in the decimal part and without minus if the answer is 0

This did not remove all trailing zeroes.

• This fails for the test case '-00.100', '-0.20' --> '-0.3' - it returns -.300 instead of -0.3. But confirm with O. P. if this is fine or not. Feb 8 at 20:09
• @IsmaelMiguel good point - I have updated. Makes it a lot longer unfortunately. It now reurns '.3', i.e. no trailing zeroes, and no leading zeroes in the integer part, which is what the challenge says (although not what the example output shows...)
– SamR
Feb 8 at 20:46
• I'm sorry it bumped the size quite a fair bit... But I've upvoted your answer. Feb 8 at 20:49
• This gives incorrect results like 99., -.3, .3 for a few of the test cases. Maybe try sed to remove trailing . / add leading 0 or -0 for those cases. Feb 9 at 14:41
• @roblogic thanks that was helpful - have updated. It still does not add a leading zero, as the spec says without any leading zeros in the integer part, trailing zeros in the decimal part and without minus if the answer is 0. I don't think that means there needs to be one.
– SamR
Feb 9 at 15:15

# Charcoal, 72 69 bytes

≔Ｅ²Ｓθ≔Ｅθ∧№ι.⌕⮌ι.η≔ΣＩＥθ⁺⁻ι.×0⁻⌈η§ηκθ≔Ｘχ⌈ηη‹θ⁰Ｉ÷↔θη¿﹪θη«.Ｗ﹪↔θη«≧÷χηＩ÷ιη


Try it online! Link is to verbose version of code. Feels very long somehow. Explanation:

≔Ｅ²Ｓθ


Input the two strings.

≔Ｅθ∧№ι.⌕⮌ι.η


See how many digits each has after the decimal (if any).

≔ΣＩＥθ⁺⁻ι.×0⁻⌈η§ηκθ


Scale them both to be integers and take the sum.

≔Ｘχ⌈ηη‹θ⁰Ｉ÷↔θη


Calculate the effect of the scaling and output the integer part of the result.

¿﹪θη«.


If the result is not an integer then output a ..

Ｗ﹪↔θη«≧÷χηＩ÷ιη


Output successive digits until the remainder is zero.

40 bytes by importing Python's decimal.Decimal:

≔ＩΣＥ²▷⪫⟦d¦.Dω⟧ecimalＳθＷ›№θ.Σ§θ±¹≔…θ⊖Ｌθθθ


Attempt This Online! Link is to verbose version of code. Explanation:

≔ＩΣＥ²▷⪫⟦d¦.Dω⟧ecimalＳθ


Input the two strings, convert them to decimal.Decimal, take the sum, then cast back to string again.

Ｗ›№θ.Σ§θ±¹


Repeat while the string contains a . and does not end in a digit 1-9...

≔…θ⊖Ｌθθ


... remove the last character.

θ


Output the final string.

# JavaScript, 210 bytes

(a,b)=>([a,c='']=a.split.,[b,d='']=b.split.,m=c[k='length'],e=(o=(g=i=>BigInt(i+c.padEnd(l=m>d[k]?m:d[k],0)))(a)+g(b,c=d)+'')[k]-l,h=o.slice(0,e),i=o.slice(e).replace(/0+$/,''),(!h|h=='-'?h+0:h)+(i&&'.'+i))  (a,b)=>( // Define function [a,c='']=a.split., // a - integer part of number a // c - decimal part of number a (default value is '') [b,d='']=b.split., // b - integer part of number b // d - decimal part of number b (default value is '') m=c[k='length'], // m - length of c // k - 'length' key e=( // e - decimal point position o= // o - sum of BigInts as string (g=i=>BigInt( // g - function which convert string to BigInt i+ c.padEnd( l=m>d[k]?m:d[k], // l - the length of longest decimal part 0 ) ))(a)+ // c.padEnd(l, '0') - adding to the end of decimal // part as many zeros as it need to // be the length of 'l' // i + c.padEnd(l, '0') - same number as in input // without decimal point and possibly // with trailing zeros g(b,c=d)+ // now c is decimal part of number b '' // added to convert BigInt to string )[k]-l, h=o.slice(0,e), // h - integer part of result i=o.slice(e).replace(/0+$/,''),           // i - decimal part of result

(!h|h=='-'?h+0:h)                         // if h is empty string or minus
// then add zero else do nothing

+                                         // concatenate of integer part of result
// and decimal part of result

(i&&'.'+i)                                // if i is empty string then
// return empty string else


Try it:

f=(a,b)=>([a,c='']=a.split.,[b,d='']=b.split.,m=c[k='length'],e=(o=(g=i=>BigInt(i+c.padEnd(l=m>d[k]?m:d[k],0)))(a)+g(b,c=d)+'')[k]-l,h=o.slice(0,e),i=o.slice(e).replace(/0+$/,''),(!h|h=='-'?h+0:h)+(i&&'.'+i)) ;[ ['1', '1'], // '2' ['0', '0'], // '0' ['9', '1'], // '10' ['001.002', '3.400'], // '4.402' ['5', '-5.0'], // '0' ['2', '-2.5'], // '-0.5' ['12345', '67890'], // '80235' ['-50.6', '20.53'], // '-30.07' ['-001.00', '00100'], // '99' ['-00.100', '-0.20'], // '-0.3' ['0.1', '0.2'], // '0.3' ['1000000000000', '-0.000000000001'], // '999999999999.999999999999' ].map(x => { console.log(f(x[0], x[1])); console.log(f(x[1], x[0])); }) # PARI/GP, 163 bytes g(s)=eval(strjoin(t=strsplit(s,".")))/10^if(#t>1,#t[2]) h(n)=if(n*=10,Str(n\1,h(n-n\1)),"") f(a,b)=Str(if(0>t=g(a)+g(b),t=-t;"-","")d=t\1,if(t-=d,Str("."h(t)),""))  Attempt This Online! # Japt, 1, 3 or 19 bytes None of these can handle the last test case as the decimal exceeds JavaScript's native number support. Links include all other test cases, taking input as an array of 2 strings. Outputs an integer, subject to floating point inaccuracies. x  Try it Outputs an string, subject to floating point inaccuracies. x s  Try it Outputs a string, with no floating point inaccuracies. x x¡X°s q. hP ÌÊÃrÔ  Try it • ['00.10', '0.200'] --> '0.30000000000000004' - it is not correct and if I'm correct the output is number not a string Feb 6 at 9:46 • Not OP but I think the many 0s are the result of floating point addition error which occurs frequently Feb 6 at 12:09 • Undone is correct, @EzioMercer; that's due to floating point inaccuracies in JavaScript. Feb 7 at 11:41 • I know why this happens and therefore I gave a lot of test cases for you to check your function for operability :) Feb 7 at 12:17 • @EzioMercer, see the very delibrerate & obvious note preceding my solutions. Feb 7 at 13:09 # Excel, 7 9 bytes =A1+B1&""  • Are the inputs considered as strings in Excel? does it work with cells formatted as text? Feb 7 at 14:21 • @Kaddath As per the specifications, the inputs are expected to be strings. And yes, it works with cells formatted as text, since that would imply a string. Feb 7 at 14:24 • If you require the inputs to be x and y, how are those input? Are you required to setup named ranges with those names and then set their value? That is beyond what's normally included for Excel answers as opposed to =A1+B1&"", which is still a good answer. Feb 7 at 15:57 • this should work on google sheets too Feb 7 at 17:52 • Fair point. If it was another language, whatever bytes were required format args as strings wouldn't be in the byte count. In Excel, you either have to format the cells as text (extra clicks or keyboard input not in the byte count) or input the values into other cells as text ('1 which doesn't count directly but requires a cell reference instead of just x in the function) or changing the formula to add your input as explicit strings (="1"+"2"&"" which also raises the byte count). This may be a question for meta but there's only a handful of Excel golfers so may not be worth it. Feb 8 at 13:25 # PHP 8.x + BC Math, 46 bytes It's a bit longer than expected, but does the job. fn($a,$b)=>rtrim(rtrim(bcadd($b,$a,99),0),'.')  This creates an anonymous function that returns the expected result. # How does it work? It uses the bcadd function to do all the math, using an obnoxiously high scale, just to be safe. That function accepts 2 strings and returns a string with the calculations made. After that, removes all 0's from the right, then the period (.). If none is found, does nothing to the result. Extremely long URL to avoid saving it on the website • I thought about bcmath too for this one, but didn't find how to enable it on TIO :D too bad there's trimmings to do Feb 9 at 8:38 • @Kaddath I wanted to try with gmp_add but I couldn't find anywhere with it enabled. Interestingly, the trimming is way shorter than removing with regular expressions. Feb 9 at 20:39 • Yeah I looked at printf but couldn't make it work with the last case in less that 2 trims Feb 10 at 16:40 # Dyalog APL, 7 bytes +/⍎¨  Try it online! Explanation: +/⍎¨ ¨ ⍝ Map each element in the array ⍎ ⍝ Execute expression, which converts from string to integer / ⍝ Reduce + ⍝ Sum  • Welcome to CGCC. It looks like this code has problems with precision: for the last test case it returns 1E12 instead of the expected result (999999999999.999999999999). Feb 8 at 4:13 • Thanks @Dingus! You are right that the last test case doesn't display as expected, but that has nothing to do with the solution. All it does is evaluate the expression as if we typed it ourselves, so we are only limited by what APL can do by default. Apparently double precision is not enough for this calculation, but we can get around that by using quad precision and making the formatting explicit to avoid scientific notation. I left it out because it looks a bit cumbersome, but I'll edit it for completeness. Feb 8 at 14:33 # bc, 162 bytes x=a+b;y=x/1;if(y==x)x=y;if(x==0||x<=-1||x>=1){print x,"\n";return} if(scale(x)>1&&x*10^length(x)%10==0){scale=1;y=x/1.0;x=y};if(x<0)print "-0",-x else print "0",x  Try it online!. Adapted from a great s.o answer. Explanation x=a+b starting out simple y=x/1;if(y==x)x=y drop trailing 0's after the decimal (99.00 --> 99 ) if(x==0||x<=-1||x>=1) if x==0 or abs(x)>=1 then just print it return preferable to else{...}, IMO. From now on x is between -1 and 1. if(scale(x)>1 if x has an gnarly decimal &&x*10^length(x)%10==0) and the last digit is 0 {scale=1;y=x/1.0;x=y} drop trailing 0's & keep significant digits (-.300 --> -.3) if(x<0)print "-0",-x (-.3 --> -0.3) else print "0",x ( .5 --> 0.5)  # Factor + decimals, 48 bytes [ [ string>decimal ] bi@ D+ unparse " " split1 ]  [ string>decimal ] bi@ ! convert both inputs to the decimal data type (arbitrary size decimals) D+ ! add them together unparse ! convert prettyprinted format to string " " split1 ! remove DECIMAL: prefix  tcl: expr$A+\$B

Tcl has no concept of a "number"; everything is a string. Some strings can be interpreted as numbers, which is what "expr" does above. Literally "take the contents of the variables "A" and "B", put a "+" between the two and treat the result as interpretable as an expression (and return the result of that expression)"

• Numbers are strings up until they aren't, where in exprs they turn into floating point numbers, and thus have precision issues e.g. 0.1+0.2`
– Jo King
Feb 8 at 1:15
• Additionally, I don't see how this takes input or outputs? TCL has procedures and can also take input for stdin, submissions should use one of those
– Jo King
Feb 8 at 1:16