44

Is there an inexpensive way to concatenate integers in csharp?

Example: 1039 & 7056 = 10397056

CountCet
  • 4,545
  • 7
  • 30
  • 39
  • 7
    Just a note - many of these (string parsing) solutions can have an OverflowException if the combined string is greater than the max integer value (or lower than the min). – Ryan Versaw Jun 18 '09 at 18:28
  • Because you didn't give any motiviation WHY you would WANT to concatenate numbers? – Cade Roux Jun 18 '09 at 19:38
  • 2
    What is the concatenation of -1039 and 7056? 1039 and -7056? -1039 and -7056? Concatenation doesn't really make a lot of sense for integers. – patros Jun 18 '09 at 21:21
  • I would never have negative numbers. These integers represent id's which are incremented and will never be negative. – CountCet Jun 19 '09 at 14:56
  • 1
    Then I hope you're using uints. The question led to some good answers, but using ints (or even uints) as an id is a bit of a code smell. Are all the ID's the same number of digits? If not you risk colliding on things like 1 & 11, 11 and 1 vs 111. – patros Jun 19 '09 at 16:00
  • A practical use for concatenating numbers would be validating an IBAN number, see http://en.wikipedia.org/wiki/International_Bank_Account_Number#Algorithms for an example. – MrBoJangles Dec 06 '13 at 22:17
  • Another practical use for concatenating integers is keeping quad-tree IDs. – Eric Mar 31 '17 at 13:58

12 Answers12

74

If you can find a situation where this is expensive enough to cause any concern, I'll be very impressed:

int a = 1039;
int b = 7056;

int newNumber = int.Parse(a.ToString() + b.ToString())

Or, if you want it to be a little more ".NET-ish":

int newNumber = Convert.ToInt32(string.Format("{0}{1}", a, b));

int.Parse is not an expensive operation. Spend your time worrying about network I/O and O^N regexes.

Other notes: the overhead of instantiating StringBuilder means there's no point if you're only doing a few concatenations. And very importantly - if you are planning to turn this back into an integer, keep in mind it's limited to ~2,000,000,000. Concatenating numbers gets very large very quickly, and possibly well beyond the capacity of a 32-bit int. (signed of course).

Rex M
  • 142,167
  • 33
  • 283
  • 313
21

I'm a bit late at the party, but recently I had to concatenate integers. With 0 < a,b < 10^9 it can be done quite fast.

static ulong concat(uint a, uint b)
{
    if (b < 10U) return 10UL * a + b;
    if (b < 100U) return 100UL * a + b;
    if (b < 1000U) return 1000UL * a + b;
    if (b < 10000U) return 10000UL * a + b;
    if (b < 100000U) return 100000UL * a + b;
    if (b < 1000000U) return 1000000UL * a + b;
    if (b < 10000000U) return 10000000UL * a + b;
    if (b < 100000000U) return 100000000UL * a + b;
    return 1000000000UL * a + b;
}

Edit: the version below might be interesting (platform target: x64).

static ulong concat(ulong a, uint b)
{
    const uint c0 = 10, c1 = 100, c2 = 1000, c3 = 10000, c4 = 100000,
        c5 = 1000000, c6 = 10000000, c7 = 100000000, c8 = 1000000000;
    a *= b < c0 ? c0 : b < c1 ? c1 : b < c2 ? c2 : b < c3 ? c3 :
         b < c4 ? c4 : b < c5 ? c5 : b < c6 ? c6 : b < c7 ? c7 : c8;
    return a + b;
}
P_P
  • 787
  • 7
  • 10
  • 8
    This should be the answer (op asked for an inexpensive way), I've benchmarked some of the answers here and this one came out on top with 36ms (vs 546ms of the accepted answer, and 718ms for the .NET-ish way). I've tested them by generating a million random integers up to 20000 (no overflows) and concatenated every one with the previous one. – user886079 Jul 09 '15 at 19:00
11

I don't think you can get any simpler than this:

static uint Concat (uint a, uint b)
{
  uint
    pow = 1;

  while (pow < b)
  {
    pow = ((pow << 2) + pow) << 1;
    a = ((a << 2) + a) << 1;
  }

  return a + b;
}

which has no memory allocations, string conversions or multiplies; or maybe:

static uint Concat (uint a, uint b)
{
  uint
    pow = 1;

  while (pow < b)
  {
    pow = ((pow << 2) + pow) << 1;
  }

  return a * pow + b;
}

If you want to concatenate two binary numbers:

static uint Concat (uint a, uint b)
{
  uint
    mask = uint.MaxValue;

  while ((mask & b) != 0)
  {
    mask <<= 1;
    a <<= 1;
  }

  return a | b;
}
Skizz
  • 69,698
  • 10
  • 71
  • 108
  • 11
    Can't get any _simpler_? I could believe this is the fastest approach, and the shifting is clever, but I'm not sure it deserves the label "simple." ;) – Doug McClean Jun 18 '09 at 19:29
  • Also, for a really tight loop you would want to profile (or at least disassemble) to see if the JIT reduces-in-strength constant multiplies by 10 to the shift pattern you have here. It might be that "pow *= 10" results in very similar results to "pow = ((pow << 2) + pow) << 1" or even that the multiply is faster for some arcane reason. – Doug McClean Jun 18 '09 at 19:33
  • Using the "*10" version on IA32, the compiler/JIT might use the intructions: lea eax,[eax*4+eax] ; add eax,eax. It's a long shot though. – Skizz Jun 19 '09 at 08:21
8
  1. string ConcatInt(int x,int y){return String.Format("{0}{1}",x,y);}
    
  2. int ConcatInt(int x,int y){
       return (x * Math.Pow(10, y.length)) + y;
    }
    

Edit Note: Fixes some mistypes. There are more type issues left. I'm just giving an outline of the answer

The second method should actually be:

static int ConcatInt2(int x, int y) {
   return (int)(x * Math.Pow(10, y.ToString().Length)) + y;
}
Mr.Wizard
  • 24,179
  • 5
  • 44
  • 125
Tim Hoolihan
  • 12,316
  • 3
  • 41
  • 54
  • #2 seems like it would be faster than a parsing to strings – tooleb Jun 18 '09 at 18:17
  • Not sure how much faster this second method really is, since you are already parsing one int to string anyway (just to get its length). I think in order for this to be really faster than just concatenating two strings, you should use the "old fashion" approach of determining numbers length. – David Božjak Jun 18 '09 at 19:46
8

inexpensive? String concatenation or formatted string is probably going to be considerably faster.

Otherwise you can do something like:

Math.Pow(10,Math.Ceiling(Math.Log10(second)))*first+second

provided first and second are integers. This is about the only way you'll do it not involving converting to a string and back, but I am extremely doubtful that it will be faster.

whatsisname
  • 5,872
  • 2
  • 20
  • 27
  • I agree, great catch on the Ceiling, and this is just about the only thing I'd be able to believe to be faster than parsing int values to strings and concatenating them. – David Božjak Jun 18 '09 at 19:51
7

If you want to concatenate many ints to a String

StringBuilder sb = new StringBuilder(1039);
sb.Append(7056);
sb.Append(1234);
sb.Append(1235);
....
sb.Append(9999);
sb.ToString();
jitter
  • 53,475
  • 11
  • 111
  • 124
3

If we want integer result then:

int result = int.Parse(input1.ToString() + input2.ToString());

For a string result do this:

string result = input1.ToString() + input2.ToString();
Kev
  • 118,037
  • 53
  • 300
  • 385
Cade Roux
  • 88,164
  • 40
  • 182
  • 265
2

The "Mathy" and "No String" method follows:

    int a = 1039;
    int b = 7056;

    int bLen = (int)Math.Ceiling(Math.Log10(b));
    int ab = (a * ((int)Math.Pow(10, bLen))) + b;

Note that it may still be slow because of the Log10 call.

C. Ross
  • 31,137
  • 42
  • 147
  • 238
2

how about this?

int c = b;
while(c > 0) {
   a *= 10;
   c /= 10;
}
a += b;
Jimmy
  • 89,068
  • 17
  • 119
  • 137
1

Not really inpexpensive, but:

string con = string.Format("{0}{1}",int1,int2);

or

string con = int1.ToString() + int2.ToString();

If you use this in a loop, I think I would use Option 1, which uses a StringBuilder internally.

Michael Stum
  • 177,530
  • 117
  • 400
  • 535
1
public int ConcatInts(int int1, int int2)
{
    return (int)(int1 * Math.Pow(10, int2.ToString().Length)) + int2;
}

Edit: Guess I wasn't the first with this solution!

Jamie Ide
  • 48,427
  • 16
  • 81
  • 117
0

// Concatenating two numbers program//

        Console.WriteLine("Enter a number for a");
        int a = int.Parse(Console.ReadLine());

        Console.WriteLine("Enter a number for b");
        int b = int.Parse(Console.ReadLine());

        int Concatenating = Convert.ToInt32(string.Format("{0}{1}", a, b));
        Console.WriteLine(Concatenating);
        Console.ReadKey();