# 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 Commented Feb 6, 2023 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 Commented Feb 6, 2023 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. Commented Feb 6, 2023 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) Commented Feb 6, 2023 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
Commented Feb 8, 2023 at 1:37

$~*+*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.) Commented Feb 16, 2023 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. Commented Feb 16, 2023 at 17:24 # 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 .add( // Plus: 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 Commented Feb 6, 2023 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.. Commented Feb 6, 2023 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)? Commented Feb 6, 2023 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. Commented Feb 6, 2023 at 14:48 • Thank you for detailed explanation! Commented Feb 6, 2023 at 14:52 # 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 Commented Feb 7, 2023 at 10:23 • @Neil does it not? Commented Feb 7, 2023 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 Commented Feb 7, 2023 at 17:21 • Hrm that would be a bug in Fig. Printing should always remove trailing zeros Commented Feb 7, 2023 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 Commented Feb 7, 2023 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. Commented Feb 8, 2023 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
Commented Feb 8, 2023 at 20:46
• I'm sorry it bumped the size quite a fair bit... But I've upvoted your answer. Commented Feb 8, 2023 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. Commented Feb 9, 2023 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
Commented Feb 9, 2023 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.

# 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 Commented Feb 6, 2023 at 9:46
• Not OP but I think the many 0s are the result of floating point addition error which occurs frequently Commented Feb 6, 2023 at 12:09
• Undone is correct, @EzioMercer; that's due to floating point inaccuracies in JavaScript. Commented Feb 7, 2023 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 :) Commented Feb 7, 2023 at 12:17
• @EzioMercer, see the very delibrerate & obvious note preceding my solutions. Commented Feb 7, 2023 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? Commented Feb 7, 2023 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. Commented Feb 7, 2023 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. Commented Feb 7, 2023 at 15:57
• this should work on google sheets too Commented Feb 7, 2023 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. Commented Feb 8, 2023 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 Commented Feb 9, 2023 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. Commented Feb 9, 2023 at 20:39
• Yeah I looked at printf but couldn't make it work with the last case in less that 2 trims Commented Feb 10, 2023 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). Commented Feb 8, 2023 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. Commented Feb 8, 2023 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

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)

# 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