9

What is the most efficient way to concatenate two positive integers in Mathematica 7?

cc[123, 4567] >> 1234567

What about more than two?

cc[123, 4, 567, 89] >> 123456789

Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125

2 Answers2

9

This will be slightly faster for many integers, than your last solution:

ToExpression[StringJoin @@ Map[IntegerString, {##}]] &

A more concise alternative is to accept a single argument, assuming it to be a list, rather than a sequence, of numbers to concatenate:

ToExpression@StringJoin@IntegerString@#&

which is based on IntegerString being Listable.

Leonid Shifrin
  • 22,449
  • 4
  • 68
  • 100
3

This only works properly for short integers because the output must be machine size, but it is the fastest I found:

Compile[{{a, _Integer}, {b, _Integer}}, 
  b + a 10^Floor[1 + Log[10, b]]
]

For longer integers, the fastest I could find is:

FromDigits[{##}, 10^IntegerLength@#2] &

For concatenating many integers, the following was faster than Fold on the one above:

FromDigits[Join @@ IntegerDigits[{##}]] & 
Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
  • In my timings the use of `IntegerLength[b]` in the compiled function is 20 times faster than the use of `Floor[...]` . – Sjoerd C. de Vries May 24 '11 at 08:33
  • @Sjoerd, is that in version 8? – Mr.Wizard May 24 '11 at 09:03
  • @Mr.Wizard `Fold` is slow because it ends up multiplying small integers by large ones a lot for long arrays. You can get a factor of 2 speed up by using divide and conquer: `Clear[cc4]; cc4[{i_}] := i; cc4[{i1_, i2_}] := FromDigits[{i1, i2}, 10^IntegerLength[i2]]; cc4[x_List] := With[{k = Quotient[Length[x] + 1, 2]}, cc4[{cc4[Take[x, k]], cc4[Drop[x, k]]}] ]`. – Sasha May 24 '11 at 12:43
  • @Mr.wizard V8, but I tried again and don't seem to be able to reproduce my timings. However, I did find an error in your first method: try `In[134]:= f[17211, 1000]` `Out[134]= 17212000` – Sjoerd C. de Vries May 24 '11 at 13:34
  • It seems like a bug, but I guess it is a binary arithmetic problem. `Floor@Log[10, 1000]` yields `2`. `Chop` fixes it. – Mr.Wizard May 24 '11 at 14:00
  • @Mr.wizard No, Floor@Log[10, 1000] yields 3. It's the +1 you added that causes the problem for 1000. This doesn't look like a job for Chop. – Sjoerd C. de Vries May 24 '11 at 14:22
  • @Sjoerd, pardon me, you misunderstand. Try: `f[a_, b_] := b + a 10^Floor[1 + Log[10, b]]; f[17211, 1000]` --- the math is right. Now try: `Compile[{{b, _Integer}}, Floor@Log[10, b]][1000]` --- it yields 2. ;-) You may be right about Chop. – Mr.Wizard May 24 '11 at 14:59
  • ps. read "May be right about..." as "of course Chop doesn't do any good at all, what was I thinking!" ;-) – Mr.Wizard May 24 '11 at 15:56
  • 1
    "The best minds make the best mistakes." Old Chinese proverb. – Sjoerd C. de Vries May 24 '11 at 16:49