将整数拆分为两个独立的整数

Split Integer into two separate Integers

假设我有

int n=123456;
int x,y=0;

如何将整数“n”一分为二。

注意:n 中的总位数将始终是 2 的倍数,例如 1234、4567、234567、345621 等...都有 2 ,4,6,8 位数字。 我想把它们分成两半。

我正在尝试使用以下代码,但它不起作用,y 变量以某种方式保留了反转的第二部分。

int x, y=0, len, digit;
int n=123456;

len=floor(log10(abs(n))) + 1;
x=n;
while((floor(log10(abs(x))) + 1)>len/2)
{
    digit=x%10;
    x=x/10;
    y=(y*10)+digit;
}
printf("First Half = %d",x);
printf("\nSecond Half = %d",y);

当输入为:

n=123456;

我得到的输出:

First Half = 123
Second Half = 654

我想要的输出:

First Half : 123

Second Half : 456

这就是我真正要做的

#include <stdio.h>
#include <math.h>

int main(void)
{
  int x, y=0, len, digit;
  int n=123456;

  len=floor(log10(abs(n))) + 1;
  x = n / pow(10, len / 2);
  y = n - x * pow(10, len / 2;
  printf("First Half = %d",x);
  printf("\nSecond Half = %d",y);
}

最简单的方法是使用 sprintf function. This takes a value and formats it according to the provided specifier. Once you have your integer represented as a string, you simply take each half of your string. Using sscanf,将过程反转回整数。

void print_both_halves(int x) {
    char str[80]; // magic number lengths
    char tmp[80];
    int len;
    int a, b;

    len = sprintf(str, "%d", x); // returns the number of chars written

    strncpy(tmp, str, len/2);
    tmp[len/2] = '[=10=]';
    sscanf(tmp, "%d", &a); // gets the first half

    strncpy(tmp, &(str[len/2]), len/2); // copies from the middle of str
    tmp[len/2] = '[=10=]';
    sscanf(tmp, "%d", &b); // gets the second half
}

这是一个演示程序。它不使用除 printf 之外的任何函数。:) 因此它是最简单的解决方案。

#include <stdio.h>

int main( void )
{
    unsigned int a[] = { 12, 1234, 123456, 12345678, 1234567890 };
    const unsigned int Base = 10;

    for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
    {   
        unsigned int divisor = Base;
        while ( a[i] / divisor > divisor ) divisor *= Base;

        printf( "%u\t%u\n", a[i] / divisor, a[i] % divisor );
    }        
}

程序输出为

1       2
12      34
123     456
1234    5678
12345   67890

如果您要使用带符号的整数类型和负数,那么程序可以如下所示

#include <stdio.h>

int main( void )
{
    int a[] = { -12, 1234, -123456, 12345678, -1234567890 };
    const int Base = 10;

    for ( size_t i = 0; i < sizeof( a ) / sizeof( *a ); i++ )
    {   
        int divisor = Base;
        while ( a[i] / ( a[i] < 0 ? -divisor : divisor ) > divisor ) divisor *= Base;

        printf( "%d\t%d\n", a[i] / divisor, a[i] % divisor );
    }        
}

它的输出是

-1      -2
12      34
-123    -456
1234    5678
-12345  -67890

因为这似乎是关于数字的问题,更具体地说是整数,所以您不应使用字符串或浮点运算。

int n = 123456;

int digits = 0;
int m = n;
while (m) {
    digits++;
    m /= 10;
}

digits /= 2;
int tmp = 0, lower_half = 0;
while (digits--) {
    tmp *= 10;
    tmp += n % 10;
    n /= 10;
}

while (tmp) {
    lower_half *= 10;
    lower_half += tmp % 10;
    tmp /= 10;
}

此处,n 包含上半部分数字,lower_half 下半部分数字。

这可以通过用除法器除模运算符来完成,即 10(NumberOfDigits/2).

#include <stdio.h>

int getNumberOfDigits(int n)
{
    int counter = 0;
    for (; n > 0; n /= 10)
        counter++;
    return counter;
}

int main(void)
{
    int n = 123456;

    int divider = 1;
    for (int i = 0; i < getNumberOfDigits(n) / 2; i++) {
        divider *= 10;
    }
    printf("%d, %d\n", n / divider, n % divider);

    return 0;
}

另一种可能性:

// split an int value into two pieces with the same number of decimal
// digits in each piece.  a couple of examples to demonstrate the output
//     iVal          iTop           iBot
//     1234            12             34
//   123456           123            456
void split_int (int iVal, int *iTop, int *iBot)
{
    int iTopx = iVal;   // save a copy of the value to be split later

    // start with assuming two decimal digits. if value is zero will still work.
    // we will then keep shifting the value right by two decimal digits as
    // we increment our divisor by one decimal digit so that we can create
    // a divisor we can then use to split the value using integer division
    // to get the top half and remainder of integer division for the bottom half.

    int iTen = 10;   // divisor value to split two decimal digits
    iVal /= 100;     // shift value right by two decimal digits
    while (iVal) {   // check to see if we are done, if not continue counting
        iTen *= 10;  // increase the divisor value we will use to split digits
        iVal /= 100; // shift value right by two decimal digits
    }

    *iTop = iTopx / iTen;  // split off top part by dividing by divisor
    *iBot = iTopx % iTen;  // split off bottom part by taking remainder
}

// test harness for the function above to try out several input data variations
// and print the results.  This is a Visual Studio Windows Console Application
// so the entry point is _tmain().
int _tmain(int argc, _TCHAR* argv[])
{
    int iTop, iBot, iVal;

    printf ("    iVal       iTop        iBot\n");    // output heading

    split_int ((iVal = 123456), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    split_int ((iVal = 12345), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    split_int ((iVal = 12), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    split_int ((iVal = 0), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    split_int ((iVal = 1234567890), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    split_int ((iVal = -1234567890), &iTop, &iBot);
    printf ("   %8.8d   %8.8d    %8.8d\n", iVal, iTop, iBot);

    return 0;
}

产生

的输出
    iVal       iTop        iBot
   00123456   00000123    00000456
   00012345   00000012    00000345
   00000012   00000001    00000002
   00000000   00000000    00000000
   1234567890   00012345    00067890
   -1234567890   -00012345    -00067890

使用字符串进行拆分的另一种变体:

#include <stdio.h>
#include <string.h>
#include <stdlib.h>

int split( int val, int *top, int *bot )
{
  char  tmp[23]; // should be large enough to hold a 64-bit decimal integer
                 // plus sign plus 0 terminator
  char  low[12] = {0};
  char high[12] = {0};

  if ( val < 0 )
    val = -val;

  sprintf( tmp, "%d", val );
  if ( strlen( tmp ) % 2 )
    return 0;

  strncpy( low, tmp, strlen( tmp ) / 2 );
  strncpy( high, tmp + strlen( tmp ) / 2, strlen( tmp ) / 2 );

  *top = (int) strtol( low, NULL, 10 );
  *bot = (int) strtol( high, NULL, 10 );

  return val;
}

int main( int argc, char **argv )
{
  if ( argc < 2 )
  {
    fprintf( stderr, "USAGE: %s integer_value_with_even_number_of_digits\n", argv[0] );
    exit( 0 );
  }

  int val = (int) strtol( argv[1], NULL, 10 );
  int lo, hi;

  if ( split( val, &lo, &hi ) )
    printf( "val: %d, lo: %d, hi: %d\n", val, lo, hi );
  else
    fprintf( stderr, "USAGE: %s integer_value_with_even_number_of_digits\n", argv[0] );

  exit( 0 );
}

一些样本运行:

[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 1
USAGE: ./splitter integer_value_with_even_number_of_digits
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 12
val: 12, lo: 1, hi: 2
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter -12
val: -12, lo: 1, hi: 2
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter -123
USAGE: ./splitter integer_value_with_even_number_of_digits
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter -1234
val: -1234, lo: 12, hi: 34
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 12345678
val: 12345678, lo: 1234, hi: 5678
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter -1234567890
val: -1234567890, lo: 12345, hi: 67890
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 012
val: 12, lo: 1, hi: 2
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 00123456
val: 123456, lo: 123, hi: 456
[fbgo448@n9dvap997]~/prototypes/splitter: ./splitter 001234567
USAGE: ./splitter integer_value_with_even_number_of_digits

您没有提到值是否必须为正数,或者前导零是否计入位数(因为它被读取为整数值而不是字符串,转换后没有前导零).

对我来说,这段代码的优点是简单。我们实质上是将数字视为一串数字以从中间拆分,因此(至少在我看来),使用字符串操作似乎是最直接的。在性能方面,这不应该比使用 log 获取数字并循环遍历它们慢。