猿问

如何确定C中整数的位数?

例如,


n = 3432, result 4


n = 45, result 2


n = 33215, result 5


n = -357, result 3

我想我可以将其转换为字符串,然后获取字符串的长度,但这似乎令人费解且容易理解。


森林海
浏览 944回答 3
3回答

宝慕林4294392

递归方法:-)int numPlaces (int n) {&nbsp; &nbsp; if (n < 0) return numPlaces ((n == INT_MIN) ? MAX_INT: -n);&nbsp; &nbsp; if (n < 10) return 1;&nbsp; &nbsp; return 1 + numPlaces (n / 10);}或迭代:int numPlaces (int n) {&nbsp; &nbsp; int r = 1;&nbsp; &nbsp; if (n < 0) n = (n == INT_MIN) ? INT_MAX: -n;&nbsp; &nbsp; while (n > 9) {&nbsp; &nbsp; &nbsp; &nbsp; n /= 10;&nbsp; &nbsp; &nbsp; &nbsp; r++;&nbsp; &nbsp; }&nbsp; &nbsp; return r;}或原始速度:int numPlaces (int n) {&nbsp; &nbsp; if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;&nbsp; &nbsp; if (n < 10) return 1;&nbsp; &nbsp; if (n < 100) return 2;&nbsp; &nbsp; if (n < 1000) return 3;&nbsp; &nbsp; if (n < 10000) return 4;&nbsp; &nbsp; if (n < 100000) return 5;&nbsp; &nbsp; if (n < 1000000) return 6;&nbsp; &nbsp; if (n < 10000000) return 7;&nbsp; &nbsp; if (n < 100000000) return 8;&nbsp; &nbsp; if (n < 1000000000) return 9;&nbsp; &nbsp; /*&nbsp; &nbsp; &nbsp; 2147483647 is 2^31-1 - add more ifs as needed&nbsp; &nbsp; &nbsp; &nbsp;and adjust this final return as well. */&nbsp; &nbsp; return 10;}修改了上面的内容,以更好地处理MININT。在任何不遵循明智的2 n二进制补码规则的怪异系统上,可能需要进一步调整。原始速度版本实际上胜过浮点版本,对其进行了以下修改:int numPlaces (int n) {&nbsp; &nbsp; if (n == 0) return 1;&nbsp; &nbsp; return floor (log10 (abs (n))) + 1;}经过一亿次迭代,我得到了以下结果:Raw speed with 0:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; 0 secondsRaw speed with 2^31-1:&nbsp; &nbsp; &nbsp; &nbsp;1 secondIterative with 2^31-1:&nbsp; &nbsp; &nbsp; &nbsp;5 secondsRecursive with 2^31-1:&nbsp; &nbsp; &nbsp; &nbsp;6 secondsFloating point with 1:&nbsp; &nbsp; &nbsp; &nbsp;6 secondsFloating point with 2^31-1:&nbsp; 7 seconds这实际上让我有些惊讶-我以为Intel芯片的FPU不错,但我想一般的FP操作仍然无法与手动优化的整数代码竞争。更新以下Stormsoul的建议:通过Stormsoul测试乘法迭代解决方案可获得4秒钟的结果,因此尽管它比除法迭代解决方案要快得多,但仍与优化的if语句解决方案不匹配。从1000个随机生成的数字中选择参数将原始速度时间缩短到2秒,因此,虽然每次都使用相同的参数似乎有些优势,但它仍然是列出的最快方法。使用-O2进行编译可以提高速度,但不能改善相对位置(我将迭代计数增加了十倍来进行检查)。任何进一步的分析都必须认真考虑CPU效率的内部工作原理(不同的优化类型,缓存的使用,分支预测,您实际拥有的CPU,房间的环境温度等等),这将妨碍我的付费工作:-)。这是一个有趣的转移,但是在某些时候,优化的投资回报变得太小了而已。我认为我们已经有了足够的解决方案来回答这个问题(毕竟,这与速度无关)。进一步更新:这将是我对此答案的最终更新,其中不包含不依赖于体系结构的明显错误。受Stormsoul勇于测量的启发,我发布了我的测试程序(根据Stormsoul自己的测试程序进行了修改)以及此处答案中显示的所有方法的一些示例图。请记住,这是在一台特定的机器上,您的行驶里程可能会因运行位置而异(这就是为什么我发布测试代码的原因)。随心所欲地处理它:#include <stdio.h>#include <stdlib.h>#include <math.h>#include <limits.h>#include <time.h>#define numof(a) (sizeof(a) / sizeof(a[0]))/* Random numbers and accuracy checks. */static int rndnum[10000];static int rt[numof(rndnum)];/* All digit counting functions here. */static int count_recur (int n) {&nbsp; &nbsp; if (n < 0) return count_recur ((n == INT_MIN) ? INT_MAX : -n);&nbsp; &nbsp; if (n < 10) return 1;&nbsp; &nbsp; return 1 + count_recur (n / 10);}static int count_diviter (int n) {&nbsp; &nbsp; int r = 1;&nbsp; &nbsp; if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;&nbsp; &nbsp; while (n > 9) {&nbsp; &nbsp; &nbsp; &nbsp; n /= 10;&nbsp; &nbsp; &nbsp; &nbsp; r++;&nbsp; &nbsp; }&nbsp; &nbsp; return r;}static int count_multiter (int n) {&nbsp; &nbsp; unsigned int num = abs(n);&nbsp; &nbsp; unsigned int x, i;&nbsp; &nbsp; for (x=10, i=1; ; x*=10, i++) {&nbsp; &nbsp; &nbsp; &nbsp; if (num < x)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return i;&nbsp; &nbsp; &nbsp; &nbsp; if (x > INT_MAX/10)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return i+1;&nbsp; &nbsp; }}static int count_ifs (int n) {&nbsp; &nbsp; if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;&nbsp; &nbsp; if (n < 10) return 1;&nbsp; &nbsp; if (n < 100) return 2;&nbsp; &nbsp; if (n < 1000) return 3;&nbsp; &nbsp; if (n < 10000) return 4;&nbsp; &nbsp; if (n < 100000) return 5;&nbsp; &nbsp; if (n < 1000000) return 6;&nbsp; &nbsp; if (n < 10000000) return 7;&nbsp; &nbsp; if (n < 100000000) return 8;&nbsp; &nbsp; if (n < 1000000000) return 9;&nbsp; &nbsp; /*&nbsp; &nbsp; &nbsp; 2147483647 is 2^31-1 - add more ifs as needed&nbsp; &nbsp; and adjust this final return as well. */&nbsp; &nbsp; return 10;}static int count_revifs (int n) {&nbsp; &nbsp; if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;&nbsp; &nbsp; if (n > 999999999) return 10;&nbsp; &nbsp; if (n > 99999999) return 9;&nbsp; &nbsp; if (n > 9999999) return 8;&nbsp; &nbsp; if (n > 999999) return 7;&nbsp; &nbsp; if (n > 99999) return 6;&nbsp; &nbsp; if (n > 9999) return 5;&nbsp; &nbsp; if (n > 999) return 4;&nbsp; &nbsp; if (n > 99) return 3;&nbsp; &nbsp; if (n > 9) return 2;&nbsp; &nbsp; return 1;}static int count_log10 (int n) {&nbsp; &nbsp; if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;&nbsp; &nbsp; if (n == 0) return 1;&nbsp; &nbsp; return floor (log10 (n)) + 1;}static int count_bchop (int n) {&nbsp; &nbsp; int r = 1;&nbsp; &nbsp; if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;&nbsp; &nbsp; if (n >= 100000000) {&nbsp; &nbsp; &nbsp; &nbsp; r += 8;&nbsp; &nbsp; &nbsp; &nbsp; n /= 100000000;&nbsp; &nbsp; }&nbsp; &nbsp; if (n >= 10000) {&nbsp; &nbsp; &nbsp; &nbsp; r += 4;&nbsp; &nbsp; &nbsp; &nbsp; n /= 10000;&nbsp; &nbsp; }&nbsp; &nbsp; if (n >= 100) {&nbsp; &nbsp; &nbsp; &nbsp; r += 2;&nbsp; &nbsp; &nbsp; &nbsp; n /= 100;&nbsp; &nbsp; }&nbsp; &nbsp; if (n >= 10)&nbsp; &nbsp; &nbsp; &nbsp; r++;&nbsp; &nbsp; return r;}/* Structure to control calling of functions. */typedef struct {&nbsp; &nbsp; int (*fnptr)(int);&nbsp; &nbsp; char *desc;} tFn;static tFn fn[] = {&nbsp; &nbsp; NULL,&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; NULL,&nbsp; &nbsp; count_recur,&nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; recursive",&nbsp; &nbsp; count_diviter,&nbsp; "&nbsp; &nbsp; &nbsp;divide-iterative",&nbsp; &nbsp; count_multiter, "&nbsp; &nbsp;multiply-iterative",&nbsp; &nbsp; count_ifs,&nbsp; &nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; if-statements",&nbsp; &nbsp; count_revifs,&nbsp; &nbsp;"reverse-if-statements",&nbsp; &nbsp; count_log10,&nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;log-10",&nbsp; &nbsp; count_bchop,&nbsp; &nbsp; "&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; binary chop",};static clock_t clk[numof (fn)];int main (int c, char *v[]) {&nbsp; &nbsp; int i, j, k, r;&nbsp; &nbsp; int s = 1;&nbsp; &nbsp; /* Test code:&nbsp; &nbsp; &nbsp; &nbsp; printf ("%11d %d\n", INT_MIN, count_recur(INT_MIN));&nbsp; &nbsp; &nbsp; &nbsp; for (i = -1000000000; i != 0; i /= 10)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf ("%11d %d\n", i, count_recur(i));&nbsp; &nbsp; &nbsp; &nbsp; printf ("%11d %d\n", 0, count_recur(0));&nbsp; &nbsp; &nbsp; &nbsp; for (i = 1; i != 1000000000; i *= 10)&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf ("%11d %d\n", i, count_recur(i));&nbsp; &nbsp; &nbsp; &nbsp; printf ("%11d %d\n", 1000000000, count_recur(1000000000));&nbsp; &nbsp; &nbsp; &nbsp; printf ("%11d %d\n", INT_MAX, count_recur(INT_MAX));&nbsp; &nbsp; /* */&nbsp; &nbsp; /* Randomize and create random pool of numbers. */&nbsp; &nbsp; srand (time (NULL));&nbsp; &nbsp; for (j = 0; j < numof (rndnum); j++) {&nbsp; &nbsp; &nbsp; &nbsp; rndnum[j] = s * rand();&nbsp; &nbsp; &nbsp; &nbsp; s = -s;&nbsp; &nbsp; }&nbsp; &nbsp; rndnum[0] = INT_MAX;&nbsp; &nbsp; rndnum[1] = INT_MIN;&nbsp; &nbsp; /* For testing. */&nbsp; &nbsp; for (k = 0; k < numof (rndnum); k++) {&nbsp; &nbsp; &nbsp; &nbsp; rt[k] = (fn[1].fnptr)(rndnum[k]);&nbsp; &nbsp; }&nbsp; &nbsp; /* Test each of the functions in turn. */&nbsp; &nbsp; clk[0] = clock();&nbsp; &nbsp; for (i = 1; i < numof (fn); i++) {&nbsp; &nbsp; &nbsp; &nbsp; for (j = 0; j < 10000; j++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; for (k = 0; k < numof (rndnum); k++) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; r = (fn[i].fnptr)(rndnum[k]);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* Test code:&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; if (r != rt[k]) {&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; printf ("Mismatch error [%s] %d %d %d %d\n",&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; fn[i].desc, k, rndnum[k], rt[k], r);&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; return 1;&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; /* */&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; }&nbsp; &nbsp; &nbsp; &nbsp; clk[i] = clock();&nbsp; &nbsp; }&nbsp; &nbsp; /* Print out results. */&nbsp; &nbsp; for (i = 1; i < numof (fn); i++) {&nbsp; &nbsp; &nbsp; &nbsp; printf ("Time for %s: %10d\n", fn[i].desc, (int)(clk[i] - clk[i-1]));&nbsp; &nbsp; }&nbsp; &nbsp; return 0;}请记住,您需要确保使用正确的命令行进行编译。特别是,您可能需要明确列出数学库才能开始log10()工作。我在Debian下使用的命令行是gcc -o testprog testprog.c -lm。而且,就结果而言,这是我的环境的排行榜:优化级别0:Time for reverse-if-statements:&nbsp; &nbsp; &nbsp; &nbsp;1704Time for&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if-statements:&nbsp; &nbsp; &nbsp; &nbsp;2296Time for&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;binary chop:&nbsp; &nbsp; &nbsp; &nbsp;2515Time for&nbsp; &nbsp; multiply-iterative:&nbsp; &nbsp; &nbsp; &nbsp;5141Time for&nbsp; &nbsp; &nbsp; divide-iterative:&nbsp; &nbsp; &nbsp; &nbsp;7375Time for&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;recursive:&nbsp; &nbsp; &nbsp; 10469Time for&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log-10:&nbsp; &nbsp; &nbsp; 26953优化级别3:Time for&nbsp; &nbsp; &nbsp; &nbsp; &nbsp;if-statements:&nbsp; &nbsp; &nbsp; &nbsp;1047Time for&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;binary chop:&nbsp; &nbsp; &nbsp; &nbsp;1156Time for reverse-if-statements:&nbsp; &nbsp; &nbsp; &nbsp;1500Time for&nbsp; &nbsp; multiply-iterative:&nbsp; &nbsp; &nbsp; &nbsp;2937Time for&nbsp; &nbsp; &nbsp; divide-iterative:&nbsp; &nbsp; &nbsp; &nbsp;5391Time for&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp;recursive:&nbsp; &nbsp; &nbsp; &nbsp;8875Time for&nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; log-10:&nbsp; &nbsp; &nbsp; 25438

蓝山帝景

二进制搜索伪算法,以获取v。中r的位数。if (v < 0 ) v=-v;r=1;if (v >= 100000000){&nbsp; r+=8;&nbsp; v/=100000000;}if (v >= 10000) {&nbsp; &nbsp; r+=4;&nbsp; &nbsp; v/=10000;}if (v >= 100) {&nbsp; &nbsp; r+=2;&nbsp; &nbsp; v/=100;}if( v>=10){&nbsp; &nbsp; r+=1;}return r;
随时随地看视频慕课网APP
我要回答