Split Integer into two separate Integers

末鹿安然 提交于 2021-02-08 13:08:39

问题


Suppose I have

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

How do I split the integer "n" in two half.

Note : The Total Number of digits in n will always be multiple of 2, e.g. 1234, 4567, 234567, 345621 etc... all have 2,4,6,8 digits. I want to divide them in half.

I am trying with following Code but it's not working, the y variable is holding reversed second part somehow.

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

When Input is :

n=123456;

Output I am getting :

First Half = 123
Second Half = 654

Output I want :

First Half : 123

Second Half : 456


回答1:


Here is a demonstrative program. It does not use any function except printf.:) Thus it is the simplest solution.

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

The program output is

1       2
12      34
123     456
1234    5678
12345   67890

If you are going to use a signed integer type and negative numbers then the program can look the following way

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

Its output is

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



回答2:


Here is actually what I would do

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



回答3:


This can be done by division an modulus operators with the divider, that is 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;
}



回答4:


Another possibility:

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

which produces the output of

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



回答5:


Since this seems to be a problem about numbers, more specifically integers, you shouldn't use either strings or floating-point operations.

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

Here, n contains the upper half of the digits, lower_half the lower ones.




回答6:


The easiest way to do this is with the 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, you reverse the process back to integer.

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] = '\0';
    sscanf(tmp, "%d", &a); // gets the first half

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



回答7:


Another variation on using strings to do the split:

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

Some sample runs:

[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

You didn't mention whether values had to be positive or not, or whether leading zeros count against the number of digits (since it's read as an integer value and not a string, there are no leading zeros after the conversion).

To me, this code has the virtue of simplicity. We're essentially treating the number as a string of digits to split down the middle, so (in my mind at least), using string operations seemed the most straightforward. Performance-wise, this shouldn't be any slower than using log to get the digits and looping through them.



来源:https://stackoverflow.com/questions/32016815/split-integer-into-two-separate-integers

标签
易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!