我想知道如何在C语言中找到一个整数的长度。
例如:
- 1 => 1
- 25 => 2
- 12512 => 5
- 0 => 1
等等。
我该如何在C语言中实现这个?
您可以对数的绝对值取以10为底的对数,向下舍入并加一。这适用于不为0的正负数,并且避免了使用任何字符串转换函数。
log10
、abs
和floor
函数由math.h
提供。例如:
int nDigits = floor(log10(abs(the_integer))) + 1;
由于 log10(0)
根据 man 3 log
的说法返回 -HUGE_VAL
,因此您应该将其包装在一个保证 the_integer != 0
的子句中。
另外,如果您对数字的长度(包括负号)感兴趣,并且输入为负数,则可能需要将最终结果加一。
int nDigits = Math.floor(Math.log10(Math.abs(the_integer))) + 1;
注意:该方法涉及到计算中的浮点数性质,可能比更直接的方法慢。请参阅Kangkan答案的评论以了解一些效率讨论。
== 0
情况,这里有一个一行代码:(the_integer == 0 ? 1 : (int)floor(log10(abs(the_integer))) + 1)
- luckydonaldint lenHelper(unsigned x) {
if (x >= 1000000000) return 10;
if (x >= 100000000) return 9;
if (x >= 10000000) return 8;
if (x >= 1000000) return 7;
if (x >= 100000) return 6;
if (x >= 10000) return 5;
if (x >= 1000) return 4;
if (x >= 100) return 3;
if (x >= 10) return 2;
return 1;
}
int printLen(int x) {
return x < 0 ? lenHelper(-x) + 1 : lenHelper(x);
}
虽然这种解决方案可能不会赢得最具创意的解决方案奖,但它非常容易理解和执行 - 因此它很快。
在Q6600上使用MSC编译器,我使用了以下循环来对其进行基准测试:
int res = 0;
for(int i = -2000000000; i < 2000000000; i += 200) res += printLen(i);
这个解决方案耗时0.062秒,使用聪明的对数方法的Pete Kirkham的第二快速解决方案需要0.115秒,几乎是两倍长。但是,对于约为10000以下的数字,聪明的对数方法更快。
以某些清晰度为代价,您可以更可靠地击败聪明的对数(至少在Q6600上):
int lenHelper(unsigned x) {
// this is either a fun exercise in optimization
// or it's extremely premature optimization.
if(x >= 100000) {
if(x >= 10000000) {
if(x >= 1000000000) return 10;
if(x >= 100000000) return 9;
return 8;
}
if(x >= 1000000) return 7;
return 6;
} else {
if(x >= 1000) {
if(x >= 10000) return 5;
return 4;
} else {
if(x >= 100) return 3;
if(x >= 10) return 2;
return 1;
}
}
}
这个解决方案在处理大数字时仍然需要0.062秒,对于小数字则会降至约0.09秒- 在两种情况下都比智能日志方法更快。 (gcc生成更快的代码; 对于这种解决方案是0.052秒,智能日志方法为0.09秒)。
int get_int_len (int value){
int l=1;
while(value>9){ l++; value/=10; }
return l;
}
第二个也适用于负数:
int get_int_len_with_negative_too (int value){
int l=!value;
while(value){ l++; value/=10; }
return l;
}
你可以编写如下函数:
unsigned numDigits(const unsigned n) {
if (n < 10) return 1;
return 1 + numDigits(n / 10);
}
if ( x < 0 ) return 1 + printed_length ( -x );
。 - Pete Kirkhamn的长度:
length = ( i==0 ) ? 1 : (int)log10(n)+1;
#include <math.h>
#include <stdio.h>
int main()
{
int x;
scanf("%d", &x);
printf("x has %d digits\n", 1 + (int)log10(x));
}
或者你可以运行一个循环来自己计算数字:通过整数除法,直到数字为0:
int numDigits = 0;
do
{
++numDigits;
x = x / 10;
} while ( x );
在第一种解决方案中,如果整数为0,则需要小心地返回1
,而且您可能还希望在处理负整数时采用-x
(如果x < 0
)的方式。
snprintf
实现方法:int count = snprintf(NULL, 0, "%i", x);
count
将因为负号而多一个单位。 - sam hocevar最高效的方法可能是使用一个快速的基于对数的方法,类似于用于确定整数中最高位设置的方法。
size_t printed_length ( int32_t x )
{
size_t count = x < 0 ? 2 : 1;
if ( x < 0 ) x = -x;
if ( x >= 100000000 ) {
count += 8;
x /= 100000000;
}
if ( x >= 10000 ) {
count += 4;
x /= 10000;
}
if ( x >= 100 ) {
count += 2;
x /= 100;
}
if ( x >= 10 )
++count;
return count;
}
#include <stdio.h>
size_t printed_length ( int x )
{
return snprintf ( NULL, 0, "%d", x );
}
int main ()
{
int x[] = { 1, 25, 12512, 0, -15 };
for ( int i = 0; i < sizeof ( x ) / sizeof ( x[0] ); ++i )
printf ( "%d -> %d\n", x[i], printed_length ( x[i] ) );
return 0;
}
snprintf()
,为什么不用snprintf(NULL, 0, "%d", x)
并且不写任何东西呢?(至少,在你的函数中使用一个静态缓冲区。) - Chris LutzINT_MIN
不起作用。使用本地的 unsigned
变量进行测试,并使用 x >= 0 ? x : -(unsigned)x
进行初始化。 - chqrlie是的,可以使用sprintf。
int num;
scanf("%d",&num);
char testing[100];
sprintf(testing,"%d",num);
int length = strlen(testing);
或者,您可以使用 log10
函数进行数学计算。
int num;
scanf("%d",&num);
int length;
if (num == 0) {
length = 1;
} else {
length = log10(fabs(num)) + 1;
if (num < 0) length++;
}
snprintf()
,这样就不必编写(和冒溢风险)任何内容了。 - Chris Lutzsprintf()
的返回值,而无需调用 strlen()
。 - phuclvint digits=1;
while (x>=10){
x/=10;
digits++;
}
return digits;
log10(10 ** n)
产生精确值。但是我不会指望所有实现都能如此。(**
表示指数运算符;C中没有这样的运算符。) - Keith Thompson