将整数拆分为两个独立的整数
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
获取数字并循环遍历它们慢。
假设我有
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
获取数字并循环遍历它们慢。