например,
n = 3432, result 4
n = 45, result 2
n = 33215, result 5
n = -357, result 3
Я думаю, я мог бы просто превратить его в строку, а затем получить длину строки, но это кажется запутанным и взломанным.
например,
n = 3432, result 4
n = 45, result 2
n = 33215, result 5
n = -357, result 3
Я думаю, я мог бы просто превратить его в строку, а затем получить длину строки, но это кажется запутанным и взломанным.
floor (log10 (abs (x))) + 1
Рекурсивный подход: -)
int numPlaces (int n) {
if (n < 0) return numPlaces ((n == INT_MIN) ? MAX_INT: -n);
if (n < 10) return 1;
return 1 + numPlaces (n / 10);
}
Или итеративный:
int numPlaces (int n) {
int r = 1;
if (n < 0) n = (n == INT_MIN) ? INT_MAX: -n;
while (n > 9) {
n /= 10;
r++;
}
return r;
}
Или необработанная скорость:
int numPlaces (int n) {
if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
if (n < 10) return 1;
if (n < 100) return 2;
if (n < 1000) return 3;
if (n < 10000) return 4;
if (n < 100000) return 5;
if (n < 1000000) return 6;
if (n < 10000000) return 7;
if (n < 100000000) return 8;
if (n < 1000000000) return 9;
/* 2147483647 is 2^31-1 - add more ifs as needed
and adjust this final return as well. */
return 10;
}
Те, что были выше, были изменены для улучшения процесса MININT. В любых странных системах, которые не следуют разумным 2 n двум правилам дополнения для целых чисел, им может потребоваться дополнительная корректировка.
Необработанная версия скорости фактически превосходит версию с плавающей запятой, измененную ниже:
int numPlaces (int n) {
if (n == 0) return 1;
return floor (log10 (abs (n))) + 1;
}
С сотней миллионов итераций я получаю следующие результаты:
Raw speed with 0: 0 seconds
Raw speed with 2^31-1: 1 second
Iterative with 2^31-1: 5 seconds
Recursive with 2^31-1: 6 seconds
Floating point with 1: 6 seconds
Floating point with 2^31-1: 7 seconds
Это на самом деле немного меня удивило - я думал, что чипы Intel имеют приличный FPU, но я полагаю, что общие операции FP по-прежнему не могут конкурировать с целым кодом, оптимизированным вручную.
Обновить следующие предложения stormsoul:
Тестирование многократно-итеративного решения by stormsoul дает результат 4 секунды, поэтому, хотя он намного быстрее, чем решение с разделителями-итерациями, оно все еще не соответствует оптимизированному решению if-statement.
Выбор аргументов из пула из 1000 произвольно сгенерированных чисел подтолкнул время сырой скорости до 2 секунд, поэтому, хотя оно появляется, возможно, было некоторое преимущество иметь один и тот же аргумент каждый раз, но он все же является самым быстрым подходом.
Компиляция с -O2 улучшала скорость, но не относительные позиции (я увеличил количество итераций в десять раз, чтобы проверить это).
Любой дальнейший анализ должен серьезно заняться внутренней работой эффективности ЦП (различные типы оптимизации, использование кэшей, предсказание ветвей, какой у вас на самом деле есть процессор, температура окружающей среды в помещении и т.д.), которые будет мешать моей оплачиваемой работе:-). Это было интересное развлечение, но в какой-то момент отдача от инвестиций для оптимизации становится слишком мала, чтобы иметь значение. Я думаю, что у нас есть достаточно решений, чтобы ответить на вопрос (который был, в конце концов, не о скорости).
Дальнейшее обновление:
Это будет мое последнее обновление этого ответа, запрещающее вопиющие ошибки, не зависящие от архитектуры. Вдохновленный бурными мерными мерками, я отправляю свою тестовую программу (модифицированную согласно собственной тестовой программе), а также некоторые примеры для всех методов, показанных в ответах здесь. Имейте в виду, что это на конкретной машине, ваш пробег может варьироваться в зависимости от того, где вы его запускаете (именно поэтому я отправляю тестовый код).
Сделайте с этим, как хотите:
#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) {
if (n < 0) return count_recur ((n == INT_MIN) ? INT_MAX : -n);
if (n < 10) return 1;
return 1 + count_recur (n / 10);
}
static int count_diviter (int n) {
int r = 1;
if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
while (n > 9) {
n /= 10;
r++;
}
return r;
}
static int count_multiter (int n) {
unsigned int num = abs(n);
unsigned int x, i;
for (x=10, i=1; ; x*=10, i++) {
if (num < x)
return i;
if (x > INT_MAX/10)
return i+1;
}
}
static int count_ifs (int n) {
if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
if (n < 10) return 1;
if (n < 100) return 2;
if (n < 1000) return 3;
if (n < 10000) return 4;
if (n < 100000) return 5;
if (n < 1000000) return 6;
if (n < 10000000) return 7;
if (n < 100000000) return 8;
if (n < 1000000000) return 9;
/* 2147483647 is 2^31-1 - add more ifs as needed
and adjust this final return as well. */
return 10;
}
static int count_revifs (int n) {
if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
if (n > 999999999) return 10;
if (n > 99999999) return 9;
if (n > 9999999) return 8;
if (n > 999999) return 7;
if (n > 99999) return 6;
if (n > 9999) return 5;
if (n > 999) return 4;
if (n > 99) return 3;
if (n > 9) return 2;
return 1;
}
static int count_log10 (int n) {
if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
if (n == 0) return 1;
return floor (log10 (n)) + 1;
}
static int count_bchop (int n) {
int r = 1;
if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
if (n >= 100000000) {
r += 8;
n /= 100000000;
}
if (n >= 10000) {
r += 4;
n /= 10000;
}
if (n >= 100) {
r += 2;
n /= 100;
}
if (n >= 10)
r++;
return r;
}
/* Structure to control calling of functions. */
typedef struct {
int (*fnptr)(int);
char *desc;
} tFn;
static tFn fn[] = {
NULL, NULL,
count_recur, " recursive",
count_diviter, " divide-iterative",
count_multiter, " multiply-iterative",
count_ifs, " if-statements",
count_revifs, "reverse-if-statements",
count_log10, " log-10",
count_bchop, " binary chop",
};
static clock_t clk[numof (fn)];
int main (int c, char *v[]) {
int i, j, k, r;
int s = 1;
/* Test code:
printf ("%11d %d\n", INT_MIN, count_recur(INT_MIN));
for (i = -1000000000; i != 0; i /= 10)
printf ("%11d %d\n", i, count_recur(i));
printf ("%11d %d\n", 0, count_recur(0));
for (i = 1; i != 1000000000; i *= 10)
printf ("%11d %d\n", i, count_recur(i));
printf ("%11d %d\n", 1000000000, count_recur(1000000000));
printf ("%11d %d\n", INT_MAX, count_recur(INT_MAX));
/* */
/* Randomize and create random pool of numbers. */
srand (time (NULL));
for (j = 0; j < numof (rndnum); j++) {
rndnum[j] = s * rand();
s = -s;
}
rndnum[0] = INT_MAX;
rndnum[1] = INT_MIN;
/* For testing. */
for (k = 0; k < numof (rndnum); k++) {
rt[k] = (fn[1].fnptr)(rndnum[k]);
}
/* Test each of the functions in turn. */
clk[0] = clock();
for (i = 1; i < numof (fn); i++) {
for (j = 0; j < 10000; j++) {
for (k = 0; k < numof (rndnum); k++) {
r = (fn[i].fnptr)(rndnum[k]);
/* Test code:
if (r != rt[k]) {
printf ("Mismatch error [%s] %d %d %d %d\n",
fn[i].desc, k, rndnum[k], rt[k], r);
return 1;
}
/* */
}
}
clk[i] = clock();
}
/* Print out results. */
for (i = 1; i < numof (fn); i++) {
printf ("Time for %s: %10d\n", fn[i].desc, (int)(clk[i] - clk[i-1]));
}
return 0;
}
Помните, что вам нужно убедиться, что вы используете правильную командную строку для ее компиляции. В частности, вам может потребоваться явно указать математическую библиотеку для работы
log10()
. Командная строка, которую я использовал в Debian, былаgcc -o testprog testprog.c -lm
.
И, с точки зрения результатов, вот панель лидеров для моей среды:
Уровень оптимизации 0:
Time for reverse-if-statements: 1704
Time for if-statements: 2296
Time for binary chop: 2515
Time for multiply-iterative: 5141
Time for divide-iterative: 7375
Time for recursive: 10469
Time for log-10: 26953
Уровень оптимизации 3:
Time for if-statements: 1047
Time for binary chop: 1156
Time for reverse-if-statements: 1500
Time for multiply-iterative: 2937
Time for divide-iterative: 5391
Time for recursive: 8875
Time for log-10: 25438
Псевдо-алгоритм двоичного поиска не получает цифр из r в v.
if (v < 0 ) v=-v;
r=1;
if (v >= 100000000)
{
r+=8;
v/=100000000;
}
if (v >= 10000) {
r+=4;
v/=10000;
}
if (v >= 100) {
r+=2;
v/=100;
}
if( v>=10)
{
r+=1;
}
return r;
Самый короткий ответ: snprintf(0,0,"%+d",n)-1
Разделите на 10 в цикле, пока результат не достигнет нуля. Число итераций будет соответствовать числу десятичных цифр.
Предполагая, что вы ожидаете получить 0 цифр в нулевом значении:
int countDigits( int value )
{
int result = 0;
while( value != 0 ) {
value /= 10;
result++;
}
return result;
}
Вы можете сделать:
floor (log10 (abs (x))) + 1
Или, если вы хотите экономить на циклах, вы могли бы просто делать сравнения
if(x<10)
return 1;
if(x<100)
return 2;
if(x<1000)
return 3;
etc etc
Это позволяет избежать любых дорогостоящих вычислительных функций, таких как журнал или даже умножение или деление. Хотя это неэлегантно, это можно скрыть, инкапсулируя его в функцию. Это не сложно или сложно поддерживать, поэтому я бы не отказался от этого подхода из-за плохой практики кодирования; Я чувствую, что это сделает бросок ребенка водой для ванны.
Версия с постоянной стоимостью, использующая сборку x86 и таблицу поиска:
int count_bsr(int i) {
struct {
int max;
int count;
} static digits[32] = {
{ 9, 1 }, { 9, 1 }, { 9, 1 }, { 9, 1 },
{ 99, 2 }, { 99, 2 }, { 99, 2 },
{ 999, 3 }, { 999, 3 }, { 999, 3 },
{ 9999, 4 }, { 9999, 4 }, { 9999, 4 }, { 9999, 4 },
{ 99999, 5 }, { 99999, 5 }, { 99999, 5 },
{ 999999, 6 }, { 999999, 6 }, { 999999, 6 },
{ 9999999, 7 }, { 9999999, 7 }, { 9999999, 7 }, { 9999999, 7 },
{ 99999999, 8 }, { 99999999, 8 }, { 99999999, 8 },
{ 999999999, 9 }, { 999999999, 9 }, { 999999999, 9 },
{ INT_MAX, 10 }, { INT_MAX, 10 }
};
register const int z = 0;
register unsigned log2;
if (i < 0) i = -i;
__asm__ __volatile__ (
"bsr %1, %0;" \
"cmovz %2, %0;"\
: "=r" (log2) \
: "rm" (i), "r"(z));
return digits[log2].count + ( i > digits[log2].max );
}
Другой, с меньшей таблицей поиска и приближением log10, взятым из здесь.
int count_bsr2( int i ) {
static const unsigned limits[] =
{0, 10, 100, 1000, 10000, 100000,
1000000, 10000000, 100000000, 1000000000};
register const int z = 0;
register int l, log2;
if (i < 0) i = -i;
__asm__ __volatile__ (
"bsr %1, %0;" \
"cmovz %2, %0;"\
: "=r" (log2) \
: "rm" (i), "r"(z));
l = (log2 + 1) * 1233 >> 12;
return (l + ((unsigned)i >= limits[l]));
}
Оба из них используют тот факт, что на x86 -INT_MIN равен INT_MIN.
Update:
В соответствии с предложением здесь приведены тайминги для count_bsr и несколько более быстрых 64-битных подпрограмм count_bsr_mod по сравнению с бинарным поиском и бинарными алгоритмами с использованием очень приятной программы тестирования paxdiablo, модифицированной для генерации множеств со случайным распределением знака. Тесты были построены с использованием gcc 4.9.2 с использованием опций "-O3 -falign-functions = 16 -falign-jumps = 16 -march = corei7-avx" и выполнялись в спокойной системе Sandy Bridge с выключенным турбо- и спящим режимами.
Time for bsr mod: 270000 Time for bsr: 340000 Time for binary chop: 800000 Time for binary search: 770000 Time for binary search mod: 470000
Источник для теста,
#include <stdint.h>
#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_bchop (int n) {
int r = 1;
if (n < 0) n = (n == INT_MIN) ? INT_MAX : -n;
if (n >= 100000000) {
r += 8;
n /= 100000000;
}
if (n >= 10000) {
r += 4;
n /= 10000;
}
if (n >= 100) {
r += 2;
n /= 100;
}
if (n >= 10)
r++;
return r;
}
static int count_bsearch(int i)
{
if (i < 0)
{
if (i == INT_MIN)
return 11; // special case for -2^31 because 2^31 can't fit in a two complement 32-bit integer
i = -i;
}
if (i < 100000) {
if (i < 1000) {
if (i < 10) return 1;
else if (i < 100) return 2;
else return 3;
} else {
if (i < 10000) return 4;
else return 5;
}
} else {
if (i < 10000000) {
if (i < 1000000) return 6;
else return 7;
} else {
if (i < 100000000) return 8;
else if (i < 1000000000) return 9;
else return 10;
}
}
}
// Integer log base 10, modified binary search.
static int count_bsearch_mod(int i) {
unsigned x = (i >= 0) ? i : -i;
if (x > 99)
if (x > 999999)
if (x > 99999999)
return 9 + (x > 999999999);
else
return 7 + (x > 9999999);
else
if (x > 9999)
return 5 + (x > 99999);
else
return 3 + (x > 999);
else
return 1 + (x > 9);
}
static int count_bsr_mod(int i) {
struct {
int m_count;
int m_threshold;
} static digits[32] =
{
{ 1, 9 }, { 1, 9 }, { 1, 9 }, { 1, 9 },
{ 2, 99 }, { 2, 99 }, { 2, 99 },
{ 3, 999 }, { 3, 999 }, { 3, 999 },
{ 4, 9999 }, { 4, 9999 }, { 4, 9999 }, { 4, 9999 },
{ 5, 99999 }, { 5, 99999 }, { 5, 99999 },
{ 6, 999999 }, { 6, 999999 }, { 6, 999999 },
{ 7, 9999999 }, { 7, 9999999 }, { 7, 9999999 }, { 7, 9999999 },
{ 8, 99999999 }, { 8, 99999999 }, { 8, 99999999 },
{ 9, 999999999 }, { 9, 999999999 }, { 9, 999999999 },
{ 10, INT_MAX }, { 10, INT_MAX }
};
__asm__ __volatile__ (
"cdq \n\t"
"xorl %%edx, %0 \n\t"
"subl %%edx, %0 \n\t"
"movl %0, %%edx \n\t"
"bsrl %0, %0 \n\t"
"shlq $32, %%rdx \n\t"
"movq %P1(,%q0,8), %q0 \n\t"
"cmpq %q0, %%rdx \n\t"
"setg %%dl \n\t"
"addl %%edx, %0 \n\t"
: "+a"(i)
: "i"(digits)
: "rdx", "cc"
);
return i;
}
static int count_bsr(int i) {
struct {
int max;
int count;
} static digits[32] = {
{ 9, 1 }, { 9, 1 }, { 9, 1 }, { 9, 1 },
{ 99, 2 }, { 99, 2 }, { 99, 2 },
{ 999, 3 }, { 999, 3 }, { 999, 3 },
{ 9999, 4 }, { 9999, 4 }, { 9999, 4 }, { 9999, 4 },
{ 99999, 5 }, { 99999, 5 }, { 99999, 5 },
{ 999999, 6 }, { 999999, 6 }, { 999999, 6 },
{ 9999999, 7 }, { 9999999, 7 }, { 9999999, 7 }, { 9999999, 7 },
{ 99999999, 8 }, { 99999999, 8 }, { 99999999, 8 },
{ 999999999, 9 }, { 999999999, 9 }, { 999999999, 9 },
{ INT_MAX, 10 }, { INT_MAX, 10 }
};
register const int z = 0;
register unsigned log2;
if (i < 0) i = -i;
__asm__ __volatile__ (
"bsr %1, %0;" \
"cmovz %2, %0;"\
: "=r" (log2) \
: "rm" (i), "r"(z));
return digits[log2].count + ( i > digits[log2].max );
}
/* Structure to control calling of functions. */
typedef struct {
int (*fnptr)(int);
const char *desc;
} tFn;
static tFn fn[] = {
{ NULL, NULL },
{ count_bsr_mod, " bsr mod" },
{ count_bsr, " bsr" },
{ count_bchop, " binary chop" },
{ count_bsearch, " binary search" },
{ count_bsearch_mod," binary search mod"}
};
static clock_t clk[numof (fn)];
int main (int c, char *v[]) {
int i, j, k, r;
int s = 1;
/* Test code:
printf ("%11d %d\n", INT_MIN, count_bsearch(INT_MIN));
//for (i = -1000000000; i != 0; i /= 10)
for (i = -999999999; i != 0; i /= 10)
printf ("%11d %d\n", i, count_bsearch(i));
printf ("%11d %d\n", 0, count_bsearch(0));
for (i = 1; i != 1000000000; i *= 10)
printf ("%11d %d\n", i, count_bsearch(i));
printf ("%11d %d\n", 1000000000, count_bsearch(1000000000));
printf ("%11d %d\n", INT_MAX, count_bsearch(INT_MAX));
return 0;
/* */
/* Randomize and create random pool of numbers. */
int p, n;
p = n = 0;
srand (time (NULL));
for (j = 0; j < numof (rndnum); j++) {
rndnum[j] = ((rand() & 2) - 1) * rand();
}
rndnum[0] = INT_MAX;
rndnum[1] = INT_MIN;
/* For testing. */
for (k = 0; k < numof (rndnum); k++) {
rt[k] = (fn[1].fnptr)(rndnum[k]);
}
/* Test each of the functions in turn. */
clk[0] = clock();
for (i = 1; i < numof (fn); i++) {
for (j = 0; j < 10000; j++) {
for (k = 0; k < numof (rndnum); k++) {
r = (fn[i].fnptr)(rndnum[k]);
/* Test code:
if (r != rt[k]) {
printf ("Mismatch error [%s] %d %d %d %d\n",
fn[i].desc, k, rndnum[k], rt[k], r);
return 1;
}
/* */
}
}
clk[i] = clock();
}
/* Print out results. */
for (i = 1; i < numof (fn); i++) {
printf ("Time for %s: %10d\n", fn[i].desc, (int)(clk[i] - clk[i-1]));
}
return 0;
}
От бит-блуждающих хаков:
Найти целочисленную базу данных 10 целого числа очевидным способом
Обратите внимание на порядок сравнения в нем.
Вот развернутый двоичный поиск без какого-либо деления или умножения. В зависимости от распределения присвоенных ему чисел он может или не может бить других, выполняемых с помощью развернутых операторов if, но всегда должен бить те, которые используют циклы и умножение/деление/log10.
При равномерном распределении случайных чисел, охватывающих весь диапазон, на моей машине он составлял в среднем 79% времени выполнения paxdiablo count_bchop(), 88% - времени count_ifs() и 97% времени count_revifs ().
С экспоненциальным распределением (вероятность числа, содержащего n цифр, равна таковой из него, которая имеет m цифр, где m ≠ n) count_ifs() и count_revifs() оба били мою функцию. Я не уверен, почему на этом этапе.
int count_bsearch(int i)
{
if (i < 0)
{
if (i == INT_MIN)
return 11; // special case for -2^31 because 2^31 can't fit in a two complement 32-bit integer
i = -i;
}
if (i < 100000) {
if (i < 1000) {
if (i < 10) return 1;
else if (i < 100) return 2;
else return 3;
} else {
if (i < 10000) return 4;
else return 5;
}
} else {
if (i < 10000000) {
if (i < 1000000) return 6;
else return 7;
} else {
if (i < 100000000) return 8;
else if (i < 1000000000) return 9;
else return 10;
}
}
}
Я наткнулся на это во время поиска в google: http://www.hackersdelight.org/hdcodetxt/ilog.c.txt
Быстрый тест показал, что выигрывают бинарные поисковые методы. код lakshmanaraj довольно хорош, Александр Коробка на 30% быстрее, Deadcode's немного быстрее (~ 10%), но я обнаружил, что следующие трюки из вышеупомянутой ссылки дают еще 10% улучшения.
// Integer log base 10, modified binary search.
int ilog10c(unsigned x) {
if (x > 99)
if (x < 1000000)
if (x < 10000)
return 3 + ((int)(x - 1000) >> 31);
// return 3 - ((x - 1000) >> 31); // Alternative.
// return 2 + ((999 - x) >> 31); // Alternative.
// return 2 + ((x + 2147482648) >> 31); // Alternative.
else
return 5 + ((int)(x - 100000) >> 31);
else
if (x < 100000000)
return 7 + ((int)(x - 10000000) >> 31);
else
return 9 + ((int)((x-1000000000)&~x) >> 31);
// return 8 + (((x + 1147483648) | x) >> 31); // Alternative.
else
if (x > 9)
return 1;
else
return ((int)(x - 1) >> 31);
// return ((int)(x - 1) >> 31) | ((unsigned)(9 - x) >> 31); // Alt.
// return (x > 9) + (x > 0) - 1; // Alt.
}
Обратите внимание, что это журнал 10, а не число цифр, поэтому digits = ilog10c(x)+1
.
Не поддерживает негативы, но это легко фиксируется с помощью -
.
int n = 437788;
int N = 1;
while (n /= 10) N++;
if (x == MININT) return 10; // abs(MININT) is not defined
x = abs (x);
if (x<10) return 1;
if (x<100) return 2;
if (x<1000) return 3;
if (x<10000) return 4;
if (x<100000) return 5;
if (x<1000000) return 6;
if (x<10000000) return 7;
if (x<100000000) return 8;
if (x<1000000000) return 9;
return 10; //max len for 32-bit integers
Очень неэлегантный. Но быстрее, чем все другие решения. Целевое подразделение и журналы FP являются дорогостоящими. Если производительность не является проблемой, решение log10 является моим любимым.
Немного подстройте язык C:
floor( log10( abs( (number)?number:1 ) ) + 1 );
НЕ используйте пол (log10 (...)). Это функции с плавающей запятой и медленные, чтобы добавить. Я считаю, что самым быстрым способом была бы эта функция:
int ilog10(int num)
{
unsigned int num = abs(num);
unsigned int x, i;
for(x=10, i=1; ; x*=10, i++)
{
if(num < x)
return i;
if(x > INT_MAX/10)
return i+1;
}
}
Обратите внимание, что версия бинарного поиска, предложенная некоторыми людьми, может быть медленнее из-за неверных предсказаний отрасли.
EDIT:
Я провел некоторое тестирование и получил некоторые действительно интересные результаты. Я назначил свою функцию вместе со всеми функциями, проверенными Pax, и функцией двоичного поиска, заданной lakshmanaraj. Тестирование выполняется с помощью следующего фрагмента кода:
start = clock();
for(int i=0; i<10000; i++)
for(int j=0; j<10000; j++)
tested_func(numbers[j]);
end = clock();
tested_func_times[pass] = end-start;
Где массив numbers [] содержит случайно сгенерированные числа во всем диапазоне типа int (запрет MIN_INT). Тестирование повторялось для каждой тестируемой функции в массиве SAME numbers []. Весь тест проводился 10 раз, результаты были усреднены по всем проходам. Код был скомпилирован с GCC 4.3.2 с уровнем оптимизации -O3.
Вот результаты:
floating-point log10: 10340ms
recursive divide: 3391ms
iterative divide: 2289ms
iterative multiplication: 1071ms
unrolled tests: 859ms
binary search: 539ms
Я должен сказать, что я очень удивился. Бинарный поиск выполнялся намного лучше, чем я думал. Я проверил, как GCC скомпилировал этот код в asm. О_О. Теперь это впечатляет. Он был оптимизирован намного лучше, чем я думал, возможно, избегая большинства отраслей по-настоящему умным образом. Неудивительно, что это БЫСТРО.
вы можете найти число цифр в числе, используя эту формулу ceil (log10 (abs (x))), где ceil возвращает целое число, большее числа
Я думаю, самый простой способ:
int digits = 0;
if (number < 0) digits = 1;
while (number) {
number /= 10;
digits++;
}
цифры дает ответ.
Простой способ найти длину (например, число цифр) целого числа со знаком:
while ( abs(n) > 9 )
{
num /= 10;
++len;
}
Где n
- это целое число, в котором вы хотите найти длину и где len
равно числу цифр в целых числах. Это работает для обоих значений n
(отрицательный или положительный).
Вызов abs()
не является обязательным, если вы работаете только с положительными целыми числами.
void main()
{
int a,i;
printf("Enter the number :");
scanf("%d",&a);
while(a>0)
{
a=a/10;
i++;
}
getch();
}