【问题标题】:Concatenate integers in C#在 C# 中连接整数
【发布时间】:2009-06-18 18:11:11
【问题描述】:

在 csharp 中是否有一种便宜的方式来连接整数?

示例:1039 & 7056 = 10397056

【问题讨论】:

  • 请注意 - 如果组合字符串大于最大整数值(或小于最小值),许多这些(字符串解析)解决方案可能会出现 OverflowException。
  • 因为你没有给出任何动机你为什么要连接数字?
  • -1039 和 7056 的串联是什么? 1039 和 -7056? -1039 和 -7056?连接对于整数并没有多大意义。
  • 我永远不会有负数。这些整数代表 id,它们会递增并且永远不会是负数。
  • 那么我希望你使用的是 uint。这个问题得到了一些很好的答案,但是使用整数(甚至是 uint)作为 id 有点代码味道。所有ID的位数都相同吗?否则,您可能会在 1 和 11、11 和 1 与 111 之类的东西上发生冲突。

标签: c#


【解决方案1】:

如果你能找到这样一个昂贵到足以引起任何担忧的情况,我会印象深刻:

int a = 1039;
int b = 7056;

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

或者,如果您希望它更“.NET-ish”:

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

int.Parse 不是一个昂贵的操作。花时间担心网络 I/O 和 O^N 正则表达式。

其他注意事项:实例化 StringBuilder 的开销意味着如果您只进行少量连接,则毫无意义。并且非常重要 - 如果您打算将其转回整数,请记住它限制为 ~2,000,000,000。连接数字很快就会变得非常大,并且可能远远超出 32 位 int 的容量。 (当然是签名)。

【讨论】:

  • 您只需要在其中一个整数上调用 .ToString()。
  • 我同意。这应该可以解决问题。如果性能在您的代码的那部分真的很重要,我会尝试针对这个问题分析不同的解决方案。
  • @Brandon 在技术上是正确的,但无论哪种方式,编译器都会执行相同的字符串转换,因此最多只能节省几次击键。
  • +1:经常让我感到惊讶的是,有多少人在寻找对这样的代码进行微优化,而不是只做有效的事情。
  • 如果使用字符串插值会更好。例如:Convert.ToInt32($"{a}{b}");
【解决方案2】:

我在聚会上有点晚了,但最近我不得不连接整数。 使用 0

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;
}

编辑:下面的版本可能很有趣(平台目标: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;
}

【讨论】:

  • 这应该是答案(操作要求以便宜的方式),我在这里对一些答案进行了基准测试,这个答案以 36 毫秒(与接受答案的 546 毫秒和 718 毫秒相比)对于 .NET 方式)。我已经通过生成高达 20000 的一百万个随机整数(没有溢出)来测试它们,并将每个整数与前一个连接起来。
【解决方案3】:

我认为没有比这更简单的了:

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;
}

没有内存分配、字符串转换或乘法;或者也许:

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

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

  return a * pow + b;
}

如果你想连接两个二进制数:

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

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

  return a | b;
}

【讨论】:

  • 找不到任何更简单的?我可以相信这是最快的方法,而且转换很聪明,但我不确定它是否配得上“简单”的标签。 ;)
  • 另外,对于一个非常紧凑的循环,您需要分析(或至少反汇编)以查看 JIT 是否将强度降低常数乘以 10 到您在此处的班次模式。可能是“pow *= 10”的结果与“pow = ((pow
  • 在 IA32 上使用 "*10" 版本,编译器/JIT 可能会使用指令: lea eax,[eax*4+eax] ;添加eax,eax。虽然这是一个很长的镜头。
【解决方案4】:

便宜?字符串连接或格式化字符串可能会快得多。

否则你可以这样做:

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

如果第一个和第二个是整数。这是不涉及转换为字符串并返回的唯一方法,但我非常怀疑它会更快。

【讨论】:

  • 我同意,在 Ceiling 上大获成功,这是我唯一能相信的比将 int 值解析为字符串并连接它们更快的方法。
【解决方案5】:
  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;
    }
    

编辑说明:修正了一些错误输入。还有更多类型问题。我只是给出答案的概要

第二种方法其实应该是:

static int ConcatInt2(int x, int y) {
   return (int)(x * Math.Pow(10, y.ToString().Length)) + y;
}

【讨论】:

  • #2 似乎比解析字符串要快
  • 不确定第二种方法到底有多快,因为无论如何您已经将一个 int 解析为字符串(只是为了获取它的长度)。我认为为了让这比仅仅连接两个字符串更快,您应该使用确定数字长度的“老式”方法。
【解决方案6】:

如果你想将多个整数连接到一个字符串

StringBuilder sb = new StringBuilder(1039);
sb.Append(7056);
sb.Append(1234);
sb.Append(1235);
....
sb.Append(9999);
sb.ToString();

【讨论】:

    【解决方案7】:

    如果我们想要整数结果,那么:

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

    对于字符串结果,请执行以下操作:

    string result = input1.ToString() + input2.ToString();
    

    【讨论】:

      【解决方案8】:

      “数学”和“无字符串”方法如下:

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

      请注意,由于 Log10 调用,它可能仍然很慢。

      【讨论】:

      • +1 虽然我不是 100% 相信这在实践中比字符串连接更快
      • 老实说,我也不相信它是。但它有效,可能值得一试。
      【解决方案9】:

      这个怎么样?

      int c = b;
      while(c > 0) {
         a *= 10;
         c /= 10;
      }
      a += b;
      

      【讨论】:

        【解决方案10】:

        不是很便宜,但是:

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

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

        如果你在循环中使用它,我想我会使用选项 1,它在内部使用 StringBuilder。

        【讨论】:

          【解决方案11】:
          public int ConcatInts(int int1, int int2)
          {
              return (int)(int1 * Math.Pow(10, int2.ToString().Length)) + int2;
          }
          

          编辑:猜猜我不是第一个使用这个解决方案的人!

          【讨论】:

            【解决方案12】:

            // 连接两个数字程序//

                    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();
            

            【讨论】:

              猜你喜欢
              • 1970-01-01
              • 1970-01-01
              • 2016-11-24
              • 2020-08-29
              • 2012-09-23
              • 2012-12-28
              • 2014-04-23
              • 1970-01-01
              • 2023-02-09
              相关资源
              最近更新 更多