2009-02-16 9 views
33

Я боюсь, что есть простой и очевидный ответ на этот вопрос. Мне нужно определить, сколько цифр имеет количество элементов, так что я могу заполнить каждый номер позиции с помощью минимума количество ведущих нулей, необходимых для поддержания выравнивания. Например, я не хочу, чтобы начальные нули, если общее число равно < 10, 1, если оно находится между 10 и 99 и т. Д.Как я могу подсчитать цифры в целых числах без строкового перевода?

Одним из решений было бы присвоить количество элементов строке и затем подсчитать символы. Тьфу! Есть ли способ лучше?

Редактировать: Я бы не подумал использовать common logarithm (я не знал, что такая вещь существует). Итак, не очевидно - мне - но определенно просто.

+1

Хотя решение логарифм получил наибольшее количество голосов до, по моему мнению, преобразование строки (которая, на удивление, был предложен только один раз) является тем лучше. Он точно отражает ваши намерения, и есть вероятность, что вы можете написать универсальный компонент, который делает это для любых предметов (а не только чисел). –

ответ

51

Это следует сделать это:

int length = (number ==0) ? 1 : (int)Math.log10(number) + 1; 
+0

он сказал, что это для графа. что означает, что область находится над натуральными числами, нет? поэтому нет необходимости в отрицательной проверке. –

+1

Последний раз, когда я проверил, число ноль имеет одну цифру, а не ноль. Значит, не должно быть числа == 0 подразумевать length = 1? –

+0

LOL. Дух. починил это. –

0

Одно из решений обеспечивается базой 10 логарифм, немного излишним.

4

Вы можете использовать время цикл, который, вероятно, будет быстрее, чем логарифм, потому что это использует только целочисленную арифметику:

int len = 0; 
while (n > 0) { 
    len++; 
    n /= 10; 
} 

Я оставляю это в качестве упражнения для читателя, чтобы настроить этот алгоритм для обработки нуля и отрицательные числа.

+0

Это хороший компромисс. «Полужесткий журнал (n)». Это будет более эффективно, чем преобразование в строку, поскольку преобразование использует это как часть его алгоритма. – gbarry

+0

fyl2x - это всего лишь 20-100 циклов. div занимает около 40, поэтому он будет принимать только 3-4 цифры до того, как этот алгоритм окажется более медленным, чем журнал. В лучших случаях журнал быстрее, чем один шаг через этот цикл ... – jheriko

+0

@jheriko: Хорошая точка. Для сырой производительности я подозреваю, что ваше статическое решение массива или даже последовательность inline сравнивается с непосредственными значениями, может оказаться самым быстрым. Но на самом деле, это расщепление волос на этом этапе! –

0

Вы можете прокручивать и удалять на 10, подсчитывать количество циклов;

int num = 423; 
int minimum = 1; 
while (num > 10) { 
    num = num/10; 
    minimum++; 
} 
12
int length = (int)Math.Log10(Math.Abs(number)) + 1; 

Вам может понадобиться для учета отрицательного знака ..

+1

+1, HOWEVER Это не удается, когда число == 0. Вам нужно сделать особый случай. –

4

Если вы собираетесь раздуть число в .Net, то

num.ToString().PadLeft(10, '0') 

может делать то, что вы хотите ,

+1

Мое толкование заключается в том, что у него есть * список * чисел, и он хочет проложить меньшие, чтобы они соответствовали ширине самого большого. Поэтому ему все же нужно выяснить, что передать для первого параметра PadLeft. –

1

Поскольку число не содержит нулей, вы все равно конвертируете их. Я не уверен, почему вы так стараетесь избежать этого, чтобы найти длину, когда конечный результат должен быть строкой в ​​любом случае.

+0

Мне нравится исследовать альтернативные решения. Иногда я изучаю вещи - например, log10. – Metaphile

+0

Я согласен, что хорошо учиться другим путям. Я просто не мог понять, почему вы сделали бы это в таком очевидном случае, когда это не было необходимо. :-) Как я уже сказал, если вы знаете, что конечным результатом будет строка, зачем тратить время на разработку способа не идти вперед и делать конверсию и делать это? –

0

Хорошо, я не могу устоять: использовать /=:

#include <stdio.h> 

int 
main(){ 
     int num = 423; 
     int count = 1; 
     while(num /= 10) 
       count ++; 
     printf("Count: %d\n", count); 
     return 0; 
} 
534 $ gcc count.c && ./a.out 
Count: 3 
535 $ 
11

Более эффективное решение, чем повторного деления будет повторяться, если заявления с размножается ... например (Где п число, в которых количество цифр требуется)

unsigned int test = 1; 
unsigned int digits = 0; 
while (n >= test) 
{ 
    ++digits; 
    test *= 10; 
} 

Если есть какое-то разумное ограничение сверху на количество элементов (например, в 32-битном диапазоне беззнаковое число), то еще лучше путь к сравнить с элементами некоторого статического массива, например

// this covers the whole range of 32-bit unsigned values 
const unsigned int test[] = { 1, 10, 100, 1000, 10000, 100000, 1000000, 10000000, 100000000, 1000000000 }; 

unsigned int digits = 10; 
while(n < test[digits]) --digits; 
+0

Я думаю, что это самое ясное и эффективное решение. Однако ваш массив должен начинаться с 0, так как 0 имеет 1 цифру. –

+0

Практически, с точки зрения производительности, таблица поиска является абсолютным лучшим решением. Мультипликация является вторым лучшим решением, так как занимает меньше времени, чем журналы или версии разделов. –

+0

Я только что понял, что есть ошибка в поисковой версии. Если n больше или равно 1000000000 (10 цифр), вы упадете с конца массива. –

2

Я бы разместил комментарий, но мой репутационный балл не предоставит мне это различие.

Все, что я хотел указать, было то, что хотя Log (10) очень изящный (читай: очень немного строк кода) решение, это, вероятно, самый больший процент для процессора.

Я думаю, что ответ Джерико, вероятно, является наиболее эффективным решением и поэтому должен быть вознагражден как таковой.

Особенно, если вы собираетесь делать это для многих чисел ..

+0

спасибо за резервную копию, но если большинство предпочитает логарифмическое решение, это их выбор. он может быть медленным, но его проще. :) – jheriko

+0

Да, я удивлен, увидев, сколько проголосовали за решение Log (не то, чтобы это ужасно) – user67143

+0

Да, это хороший момент для поднятия, тот, который, как я считаю, многие игнорируются. И добро пожаловать в «комментирующий клуб»! ;-) – Cerebrus