Как объединить два целых числа в C

Переполнение стека отвечает на этот вопрос на многих других языках, но не на C. Поэтому я думал, что попрошу, поскольку у меня такая же проблема.

Как конкатенировать два целых числа в C?

Пример:

x = 11;
y = 11;

Мне хотелось бы z следующим образом:

z = 1111;

Другие примеры пытаются сделать это со строками. Каков способ сделать это без строк?

Я ищу эффективный способ сделать это на C, потому что в моем конкретном использовании это происходит во временной критичной части кода.

Спасибо в Advance!

Ответ 1

unsigned concatenate(unsigned x, unsigned y) {
    unsigned pow = 10;
    while(y >= pow)
        pow *= 10;
    return x * pow + y;        
}

Доказательство компиляция/правильность/скорость

Я избегаю функций log10 и pow, потому что я уверен, что они используют с плавающей запятой и медленны, поэтому это может быть быстрее на вашем компьютере. Может быть. Профиль.

Ответ 2

z = x * pow(10, log10(y)+1) + y;

Объяснение:

Сначала вы получите количество цифр переменной, которая должна быть второй:

int digits = log10(y)+1;  // will be 2 in your example

Затем вы меняете другую переменную, умножая ее на 10 цифр.

int shifted = x * pow(10, digits);   // will be 1100 in your example

Наконец, вы добавите вторую переменную:

z = shifted + y;   // 1111

Или в одной строке:

z = x * pow(10, (int)log10(y)+1) + y;

Ответ 3

int myPow(int x, int p)
{
     if (p == 0) return 1;
     if (p == 1) return x;

     int tmp = myPow(x, p/2);
     if (p%2 == 0) return tmp * tmp;
     else return x * tmp * tmp;
}
int power = log10(y);
z = x*myPow(10,power+1)+y;

Здесь я бесстыдно скопировал myPow из fooobar.com/questions/79794/...

Ответ 4

Это может быть не оптимальное или быстрое решение, но никто не упомянул об этом, и он простой и может быть полезен.

Вы можете использовать sprintf() и strtol().

char str[100];
int i=32, j=45;
sprintf(str, "%d%d", i, j);
int result=strtol(str, NULL, 10);

Сначала вы записываете в строку числа, следующие за другим, с помощью sprintf() (как и вы печатаете на stdout с помощью printf()), а затем конвертируете результирующую строку в число с strtol().

strtol() возвращает a long, который может быть значением, большим, чем то, что может быть сохранено в int, поэтому вы можете сначала проверить полученное значение.

int result;
long rv=strtol(str, NULL, 10);
if(rv>INT_MAX || rv<INT_MIN || errno==ERANGE)
{
    perror("Something went wrong.");
}
else
{
    result=rv;
}

Если значение, возвращаемое strtol(), не находится в пределах диапазона int (т.е. не между (включая) INT_MIN и INT_MAX), произошла ошибка. INT_MIN и INT_MAX взяты из limits.h.

Если значение в строке слишком велико, чтобы быть представленным в long, errno будет установлен в ERANGE (из errno.h) из-за переполнения.

Читайте о strtol() здесь.

Edit:

Как отмечал просветительский комментарий chqrlie, отрицательные числа могут вызвать проблемы с этим подходом.

Вы можете использовать это или модификацию этого, чтобы обойти это.

char str[100], temp[50];
int i=-32, j=45, result;
sprintf(temp, "%+d", j);
sprintf(str, "%d%s", i, temp+1);
long rv=strtol(str, NULL, 10);

Сначала напечатайте второй номер массива символов temp вместе со своим знаком.

+ в %+d приведет к печати знака номера.

Теперь напечатайте первое число и второе число до str, но без знаковой части второго номера. Мы пропускаем знаковое число второго числа, игнорируя первый символ в temp.

Наконец выполняется strtol().

Ответ 5

здесь другой способ сделать это:

int concat(int x, int y) {
    int temp = y;
    while (y != 0) {
        x *= 10;
        y /= 10;
    }
    return x + temp;
}

кто знает, какую производительность вы получите. просто попробуйте и посмотрите.

Ответ 6

Возможно, это сработает:

int x=11,y=11,temp=0;
int z=x;
while(y>0)
{
    // take reciprocal of y into temp
    temp=(temp*10)+(y%10);       
    y=y/10;
}
while(temp>0)
{
    // take each number from last of temp and add to last of z
    z=(z*10)+(temp%10);      
    temp=temp/10;
}

код длинный, но простой. исправьте меня, если будут какие-то ошибки.

Ответ 7

Вот вариант ответа @Mooing Duck, который использует таблицу поиска для кратных 10 (для платформы с медленным целым умножением). Он также возвращает unsigned long long, чтобы разрешить большие значения, и использует unsigned long long в таблице поиска учтите комментарий @chqrlie о бесконечных циклах. Если объединенные входы могут быть не превышены без знака, это может быть изменено.

static const unsigned long long pow10s[] = {
   10,100,1000,10000,100000,1000000,10000000,100000000,1000000000,10000000000
};
unsigned long long concat(unsigned x, unsigned y) {
    const unsigned long long *p = pow10s;
    while (y >= *p) ++p;
    return *p * x +y;        
}

Ответ 8

Вы также можете использовать макрос для объединения строк (простой способ)

#include<stdio.h>
#define change(a,b) a##b
int main()
 {
    int y;
    y=change(12,34);
    printf("%d",y);
    return 0;
 }

У него есть один недостаток. Мы не можем передавать аргументы в этом методе

Ответ 9

#include<iostream>
using namespace std;

int main()
{
    int a=0,b=0,count=0,c=0,t=0;
    cout<<"enter 2 no"<<endl;
    cin>>a>>b;
    t=b;

    while(b!=0)
    {
        b=b/10;
        count++;
    }

    while(count!=0)
    {
        a=a*10;
        count--;
        c=a+t;
    }

    cout<<"concate no is:"<<c;
}