2009-06-18 37 views
26

Có cách nào không tốn kém cách ghép các số nguyên trong csharp?Ghép số nguyên trong C#

Ví dụ: 1039 & 7056 = 10397056

+7

Chỉ cần một lưu ý - nhiều trong số này (chuỗi phân tích cú pháp) các giải pháp có thể có một OverflowException nếu chuỗi kết hợp là lớn hơn giá trị số nguyên max (hoặc thấp hơn min). –

+0

Tại sao tôi bị bỏ phiếu? – CountCet

+0

Bởi vì bạn không đưa ra bất kỳ động lực nào Tại sao bạn muốn ghép nối các số? –

Trả lời

49

Nếu bạn có thể tìm thấy một tình huống mà điều này là đủ tốn kém để gây ra bất kỳ mối quan tâm, tôi sẽ rất ấn tượng:

int a = 1039; 
int b = 7056; 

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

Hoặc, nếu bạn muốn nó được nhiều hơn một chút "NET-ish":

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

int.Parse là không một hoạt động tốn kém. Dành thời gian của bạn lo lắng về mạng I/O và O^N regexes.

Ghi chú khác: chi phí của việc tạo chuỗi StringBuilder nghĩa là không có điểm nào nếu bạn chỉ thực hiện một vài kết nối. Và rất quan trọng - nếu bạn lập kế hoạch để biến điều này trở lại thành một số nguyên, hãy nhớ rằng nó bị giới hạn ~ 2.000.000.000. Các số ghép nối rất lớn rất nhanh và có thể vượt quá khả năng của một int 32 bit. (đã ký của khóa học).

+2

Bạn chỉ cần gọi .ToString() trên một trong các số nguyên. – Brandon

+0

Tôi đồng ý. Cái này cần phải dùng mẹo. Nếu hiệu suất là thực sự quan trọng trong đó một phần của mã của bạn tôi muốn cố gắng để hồ sơ các giải pháp khác nhau cho vấn đề này. –

+4

@ Brandon đúng về mặt kỹ thuật, nhưng trình biên dịch thực hiện chuyển đổi chuỗi giống nhau theo một trong hai cách, do đó, nó chỉ tiết kiệm được một vài tổ hợp phím ở mức tốt nhất. –

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

Chỉnh sửa Lưu ý: Sửa chữa một số mistypes. Còn nhiều vấn đề khác nữa. Tôi chỉ đưa ra một phác thảo của câu trả lời

Phương pháp thứ hai thực sự nên là:

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

# 2 có vẻ như nó sẽ nhanh hơn việc phân tích cú pháp thành chuỗi – tooleb

+0

Bạn không chắc chắn phương thức thứ hai này nhanh hơn bao nhiêu, vì bạn đã phân tích cú pháp một chuỗi thành chuỗi nào đó (chỉ để có được chiều dài của nó). Tôi nghĩ rằng để điều này thực sự nhanh hơn là chỉ nối hai chuỗi, bạn nên sử dụng phương pháp "thời trang cũ" để xác định chiều dài số. –

3

Nếu chúng ta muốn kết quả số nguyên thì:

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

Đối với một chuỗi kết quả làm việc này:

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

Phương thức "Mathy" và "No String" sau:

int a = 1039; 
    int b = 7056; 

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

Lưu ý rằng nó vẫn có thể chậm do cuộc gọi Log10.

+1

+1 mặc dù tôi không tin tưởng 100% rằng điều này nhanh hơn trong thực tế hơn là ghép nối chuỗi –

+0

Thành thật mà nói, tôi cũng không tin là nó. Nhưng nó hoạt động và nó có thể đáng để thử. –

8

không tốn kém? Chuỗi nối hoặc chuỗi định dạng có thể sẽ nhanh hơn đáng kể.

Nếu không, bạn có thể làm điều gì đó như:

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

cung cấp đầu tiên và thứ hai là các số nguyên. Đây là cách duy nhất bạn sẽ làm điều đó không liên quan đến việc chuyển đổi một chuỗi và trở lại, nhưng tôi cực kỳ nghi ngờ rằng nó sẽ nhanh hơn.

+0

+1 Cuộc gọi tốt trên Trần nhà. –

+0

Tôi đồng ý, nắm bắt tuyệt vời trên Trần, và đây chỉ là điều duy nhất tôi có thể tin là nhanh hơn phân tích các giá trị int thành chuỗi và nối chúng lại. –

6

Nếu bạn muốn nối nhiều ints vào một String

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

Không thực sự inpexpensive, nhưng:

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

hoặc

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

Nếu bạn sử dụng điều này trong một vòng lặp , Tôi nghĩ rằng tôi sẽ sử dụng Option 1, trong đó sử dụng một StringBuilder trong nội bộ.

1
public int ConcatInts(int int1, int int2) 
{ 
    return (int)(int1 * Math.Pow(10, int2.ToString().Length)) + int2; 
} 

Chỉnh sửa: Đoán tôi không phải là người đầu tiên có giải pháp này!

7

Tôi không nghĩ rằng bạn có thể nhận được bất kỳ đơn giản hơn này:

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

mà không có phân bổ bộ nhớ, chuyển đổi chuỗi hoặc nhân lên; hoặc có thể:

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

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

    return a * pow + b; 
} 

Nếu bạn muốn nối hai số nhị phân:

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

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

    return a | b; 
} 
+7

Không thể nhận bất kỳ _simpler_ nào? Tôi có thể tin đây là cách tiếp cận nhanh nhất, và sự dịch chuyển là thông minh, nhưng tôi không chắc nó xứng đáng với nhãn "đơn giản". ;) –

+0

Ngoài ra, đối với một vòng lặp thực sự chặt chẽ, bạn sẽ muốn cấu hình (hoặc ít nhất là tháo rời) để xem nếu JIT giảm-trong-sức mạnh liên tục nhân với 10 đến mô hình thay đổi bạn có ở đây. Nó có thể là "pow * = 10" dẫn đến kết quả rất giống với "pow = ((pow << 2) + pow) << 1" hoặc thậm chí là số nhân nhanh hơn đối với một số lý do phức tạp. –

+0

Sử dụng phiên bản "* 10" trên IA32, trình biên dịch/JIT có thể sử dụng lệnh intructions: lea eax, [eax * 4 + eax]; thêm eax, eax. Đó là một shot dài mặc dù. – Skizz

2

thế nào về điều này?

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

Tôi hơi muộn ở bữa tiệc, nhưng gần đây tôi phải ghép các số nguyên. Với 0 < a, b < 10^9 nó có thể được thực hiện khá nhanh.

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

Chỉnh sửa: phiên bản bên dưới có thể thú vị (mục tiêu nền tảng: 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; 
} 
+6

Điều này sẽ là câu trả lời (op hỏi cho một cách rẻ tiền), tôi đã chuẩn bị một số câu trả lời ở đây và điều này xuất hiện trên đầu trang với 36ms (so với 546ms của câu trả lời được chấp nhận và 718ms cho cách .NET-ish). Tôi đã thử nghiệm chúng bằng cách tạo ra một triệu số nguyên ngẫu nhiên lên đến 20000 (không tràn) và nối tất cả với số nguyên trước đó. – user886079

0

// Kết nối hai số chương trình //

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