タイトル通りですが、C/C++で整数の桁数を最短で求めるにはどうすればよいでしょうか?
実験として、以下のようなプログラムを書いて、①10で割っていく、②常用対数を使う、の2通りを試してみました。
C
1#include <stdio.h> 2#include <math.h> 3#include <time.h> 4 5 6void countDigit(int n) 7{ 8 int digit = 1; 9 clock_t start,end; 10 11 start = clock(); 12 13 while((n /= 10) != 0) 14 digit++; 15 16 end = clock(); 17 18 printf("countDigit() digit::%d time::%dms\n",digit,(int)(end - start)); 19} 20 21void countDigitUsingLog(int n) 22{ 23 clock_t start,end; 24 int digit; 25 26 start = clock(); 27 28 digit = log10(n) + 1; 29 30 end = clock(); 31 printf("countDigitUsingLog() digit::%d time::%dms\n",digit,(int)(end - start)); 32} 33 34int main(void) 35{ 36 int n = 0; 37 int i; 38 39 for(i = 1;i < 10;i++) { 40 n = n * 10 + i; 41 printf("N = %d\n",n); 42 countDigit(n); 43 countDigitUsingLog(n); 44 printf("\n"); 45 } 46 47 return 0; 48} 49
実行結果::
N = 1 countDigit() digit::1 time::3ms countDigitUsingLog() digit::1 time::47ms N = 12 countDigit() digit::2 time::1ms countDigitUsingLog() digit::2 time::12ms N = 123 countDigit() digit::3 time::2ms countDigitUsingLog() digit::3 time::2ms N = 1234 countDigit() digit::4 time::1ms countDigitUsingLog() digit::4 time::2ms N = 12345 countDigit() digit::5 time::1ms countDigitUsingLog() digit::5 time::2ms N = 123456 countDigit() digit::6 time::2ms countDigitUsingLog() digit::6 time::2ms N = 1234567 countDigit() digit::7 time::1ms countDigitUsingLog() digit::7 time::2ms N = 12345678 countDigit() digit::8 time::2ms countDigitUsingLog() digit::8 time::2ms N = 123456789 countDigit() digit::9 time::2ms countDigitUsingLog() digit::9 time::3ms
僕の実行環境では、①は桁数に関わらず一定の速さ、②は3桁目あたりから①の速さに追いつく、といった結果になりました。この結果だけみると①のほうが良いのではないかの思ったのですが、C/C++は初心者に毛が生えた程度の知識しかないので、検証方法にあまり自信がありません。この結果を信じてもよいのでしょか?また、他にもっと良い方法があれば教えてください。
<実行環境>
Ubuntu 16.04 LTS
CPU : AMD A4-5000 APU with Radeon(TM) HD Graphics
gcc version 5.4.1 20160904 (Ubuntu 5.4.1-2ubuntu1~16.04)
<2017/1/23 追記>
皆さん回答ありがとうございました!ikedasさんのものとほとんど変わりませんが、皆さんが回答してくださったものを一通り僕の環境でも試してみました。与えられる整数値の桁数の範囲が分かっているなら、2分探索が一番良さそうです。とても勉強になりました、みなさん本当にありがとうございました!以下修正版と結果です。
C
1#include <stdio.h> 2#include <math.h> 3#include <time.h> 4#include <limits.h> 5#include <assert.h> 6 7#define LOOP 10000000 8 9 10void countDigit(int n) 11{ 12 int digit = 1; 13 clock_t start,end; 14 15 start = clock(); 16 17 for(size_t i = 0;i < LOOP; ++i) { 18 while((n /= 10) != 0) 19 digit++; 20 } 21 22 end = clock(); 23 24 printf("%-25s\tdigit::%d\ttime::%fs\n", 25 "countDigit()",digit,((double)end - start)/CLOCKS_PER_SEC); 26} 27 28void countDigitUsingLog(int n) 29{ 30 clock_t start,end; 31 int digit; 32 33 start = clock(); 34 35 for(size_t i = 0;i < LOOP; ++i) 36 digit = log10(n) + 1; 37 38 end = clock(); 39 40 printf("%-25s\tdigit::%d\ttime::%fs\n", 41 "countDigitUsingLog()",digit,((double)end - start)/CLOCKS_PER_SEC); 42} 43 44void countDigitBinary(int n) 45{ 46 int digit; 47 clock_t start,end; 48 49 start = clock(); 50 51 for(size_t i = 0;i < LOOP; ++i) { 52 53 if (n < 100000) { 54 if (n < 1000) { 55 if (n < 10) 56 digit = 1; 57 else if (n < 100) 58 digit = 2; 59 else 60 digit = 3; 61 } else { 62 if (n < 10000) 63 digit = 4; 64 else 65 digit = 5; 66 } 67 } else { 68 if (n < 10000000) { 69 if (n < 1000000) 70 digit = 6; 71 else 72 digit = 7; 73 } else { 74 if (n < 100000000) 75 digit = 8; 76 else if (n < 1000000000) 77 digit = 9; 78 else 79 digit = 10; 80 } 81 } 82 } 83 84 85 end = clock(); 86 87 printf("%-25s\tdigit::%d\ttime::%fs\n", 88 "countDigitBinary()",digit,((double)end - start)/CLOCKS_PER_SEC); 89} 90 91int digitPoor(int n) 92{ 93 assert(INT_MAX == 2147483647); 94 assert(n >= 0); 95 96 if (n < 10) return 1; 97 if (n < 100) return 2; 98 if (n < 1000) return 3; 99 if (n < 10000) return 4; 100 if (n < 100000) return 5; 101 if (n < 1000000) return 6; 102 if (n < 10000000) return 7; 103 if (n < 100000000) return 8; 104 if (n < 1000000000) return 9; 105 return 10; 106} 107 108void countDigitPoor(int n) 109{ 110 clock_t start,end; 111 int digit; 112 113 start = clock(); 114 for (size_t i=0; i < 10000000; ++i) { 115 digit = digitPoor(n); 116 } 117 end = clock(); 118 printf("%-25s\tdigit::%d\ttime::%fs\n", 119 "countDigitPoor()",digit,((double)end - start)/CLOCKS_PER_SEC); 120} 121 122void countDigitUsingSprintf(int n) 123{ 124 clock_t start,end; 125 int digit; 126 char dummy[10]; 127 128 start = clock(); 129 130 for(size_t i = 0;i < LOOP; ++i) 131 digit = sprintf(dummy, "%d", n); 132 133 end = clock(); 134 printf("%-25s\tdigit::%d\ttime::%fs\n", 135 "countDigitUsingSprintf()",digit,((double)end - start)/CLOCKS_PER_SEC); 136} 137 138void countForLoop() 139{ 140 clock_t start,end; 141 volatile int x=1; 142 143 start = clock(); 144 145 for (size_t i = 0; i < LOOP; ++i) 146 { 147 x=i; 148 } 149 150 end = clock(); 151 152 printf("%-25s\t--------\ttime::%fs\n", 153 "countForLoop()",((double)end - start)/CLOCKS_PER_SEC); 154} 155 156int main(void) 157{ 158 int n = 0; 159 int i; 160 161 for(i = 1;i < 10;i++) { 162 n = n * 10 + i; 163 printf("N = %d\n",n); 164 countForLoop(); 165 countDigit(n); 166 countDigitUsingLog(n); 167 countDigitBinary(n); 168 countDigitPoor(n); 169 countDigitUsingSprintf(n); 170 printf("\n"); 171 } 172 173 return 0; 174} 175
N = 1 countForLoop() -------- time::0.045770s countDigit() digit::1 time::0.100439s countDigitUsingLog() digit::1 time::0.378452s countDigitBinary() digit::1 time::0.053568s countDigitPoor() digit::1 time::0.079120s countDigitUsingSprintf() digit::1 time::2.265236s N = 12 countForLoop() -------- time::0.043182s countDigit() digit::2 time::0.100408s countDigitUsingLog() digit::2 time::1.012793s countDigitBinary() digit::2 time::0.060286s countDigitPoor() digit::2 time::0.092724s countDigitUsingSprintf() digit::2 time::2.341804s N = 123 countForLoop() -------- time::0.042746s countDigit() digit::3 time::0.100416s countDigitUsingLog() digit::3 time::1.004158s countDigitBinary() digit::3 time::0.060143s countDigitPoor() digit::3 time::0.108729s countDigitUsingSprintf() digit::3 time::2.442325s N = 1234 countForLoop() -------- time::0.045008s countDigit() digit::4 time::0.100400s countDigitUsingLog() digit::4 time::1.004526s countDigitBinary() digit::4 time::0.048930s countDigitPoor() digit::4 time::0.132441s countDigitUsingSprintf() digit::4 time::2.530141s N = 12345 countForLoop() -------- time::0.042238s countDigit() digit::5 time::0.100400s countDigitUsingLog() digit::5 time::1.008050s countDigitBinary() digit::5 time::0.060654s countDigitPoor() digit::5 time::0.144062s countDigitUsingSprintf() digit::5 time::2.624742s N = 123456 countForLoop() -------- time::0.042451s countDigit() digit::6 time::0.100724s countDigitUsingLog() digit::6 time::1.008027s countDigitBinary() digit::6 time::0.058717s countDigitPoor() digit::6 time::0.177779s countDigitUsingSprintf() digit::6 time::2.751899s N = 1234567 countForLoop() -------- time::0.041235s countDigit() digit::7 time::0.100376s countDigitUsingLog() digit::7 time::1.004352s countDigitBinary() digit::7 time::0.069315s countDigitPoor() digit::7 time::0.193293s countDigitUsingSprintf() digit::7 time::2.825540s N = 12345678 countForLoop() -------- time::0.041624s countDigit() digit::8 time::0.100474s countDigitUsingLog() digit::8 time::1.004698s countDigitBinary() digit::8 time::0.075757s countDigitPoor() digit::8 time::0.215140s countDigitUsingSprintf() digit::8 time::2.937961s N = 123456789 countForLoop() -------- time::0.043923s countDigit() digit::9 time::0.100387s countDigitUsingLog() digit::9 time::1.004096s countDigitBinary() digit::9 time::0.094569s countDigitPoor() digit::9 time::0.254226s countDigitUsingSprintf() digit::9 time::3.033319s
回答6件
あなたの回答
tips
プレビュー