1. Este site usa cookies. Ao continuar a usar este site está a concordar com o nosso uso de cookies. Saber Mais.

quantos dígitos tem um número??

Discussão em 'Programação' iniciada por toblesu, 7 de Setembro de 2008. (Respostas: 30; Visualizações: 4848)

  1. toblesu

    toblesu Power Member

    Boas...

    Assim de repente deu-me uma branca.... precisava duma função análoga ao strlen() para saber o número de digítos de um inteiro.

    já andei à procura, mas o mais provável é não ter efectuado bem a pesquisa!

    Se me puderem desenrascar, facilitava-me muito, estou apertada com o tempo para continuar a fazer pesquisas sem sucesso! :(

    Obrigado
     
  2. Yumon

    Yumon Power Member

    Bom não sei que linguagem queres... Mas basta ires dividindo o número por 10 e fazendo o arredondamento ás unidades e com um contador vais incrementando, quando o número for 0 termina o ciclo...

    EDIT: Quanto ao nome da função em si não sei qual será... mas visto ser um algoritmo de fácil implementação...
     
    Última edição: 7 de Setembro de 2008
  3. syMMys

    syMMys Banido

    Matematicamente: floor( log10( inteiro ) ) + 1

    ou seja, a parte inteira do logaritmo de base 10 do número inteiro do qual pretendes saber quantos algarismos tem, mais um

    É um canhão para matar uma mosca mas é isto. Há outras coisas mais rápidas mas mais demoradas de explicar.
     
    Última edição: 7 de Setembro de 2008
  4. The_True_Eue

    The_True_Eue Power Member

    Se usares divisão inteira não há arredondamentos nem logaritmos à mistura. Não sei o que será mais eficiente, 10 divisões ou um logaritmo e dois casts... Depende...
    Em C:
    Código:
    int dgtlen(int n)
    {
        if(n == 0)
            return 1;
        else
        {
            int c;
            for(c = 0; n; n /= 10)
                c++;
            return c;
        }
    }
    
     
    Última edição: 7 de Setembro de 2008
  5. neutral

    neutral Power Member

    nao penso que seja isso que ele pretende..

    pelo que percebi

    1234

    e um numero com 4 digitos

    logo

    tenta converter para uma string e aplica o strlen

    ou faz uma função porque nao acho que haja nenhuma na std lib de c
     
  6. The_True_Eue

    The_True_Eue Power Member

    É mesmo aquilo (qualquer uma) que ele pretende.
    Funciona, mas é péssimo.
     
  7. syMMys

    syMMys Banido


    Cheira-me que é mais as "n" divisões inteiras. Qual é a rapidez da instrução x86 DIV ou IDIV? :D Tirando algoritmos com look-up tables ou fazer as contas em base 2 com shifts e depois passar para base 10 (implica uma ou duas divisões em vírgula flutuante)... sei lá...

    Depende do que se pretende. Em alguns casos até a opção INT->STRING ->STRLEN pode ser encarada. Depende da "pressão" :D
     
  8. toblesu

    toblesu Power Member

    de facto é mesmo isso, posso nao ter sido muito explicito,
    portando: 1234 -> 4 digitos.

    tentei implementar a funcao que me deram mas não correu la muito bem.,....

    vou ver melhor, mas a ideia é mesmo essa....

    (estou a programar em c++)


    mais uma vez, obrigado!
     
  9. toblesu

    toblesu Power Member

    estava a implementar mal.....

    consegui!! usei a função sugerida! Muito obrigado.
     
  10. The_True_Eue

    The_True_Eue Power Member

    Se o número em questão for, por exemplo, um googol (n = 10^100, mais que o número de partículas subatómicas no universo observável), são 101 dígitos, logo 101 divisões e não 10^100!
    Numa máquina de 32 bits só consegues representar números até 2^32, que tem 10 dígitos. Numa de 64 bits, são 20 dígitos. Logo, na pior das hipóteses, 20 divisões, 20 incrementos e 21 comparações. Nada mau...

    Com logaritmos... Bem, calcular logaritmos implica o uso de vírgula flutuante, logo cast para float/double e cast para inteiro no fim. O que é complicado é o logaritmo. Não sei como será calculado numa FPU actual, mas de certeza que é uma operação mais pesada que divisões.

    Mas, qualquer destas duas situações funciona completamente dentro do processador, porque podem ser executadas apenas em registos.

    Agora, fazer uma string implica acesso à memória. Pois, enquanto escreves a string na memória, o processador tem tempo para fazer as divisões todas ou até mesmo o cálculo do logaritmo. Depois ainda tens de contar os caracteres...

    E... para fazer a string a partir de um inteiro usa-se um algoritmo semelhante ao que eu apresentei...

    Peço desculpa pelo core dump...
     
    Última edição: 7 de Setembro de 2008
  11. syMMys

    syMMys Banido

    Quando disse "n" divisões era no sentido de ser um determinado número de divisões e não um valor igual ao inteiro do qual se pretende saber quantos dígitos tem. Creio que contextualizaste o meu post no seguimento do teu post com o algoritmo onde usas a variável n.

    Como sabes, no mundo académico quando se usa o jargão "n" coisas é no sentido de ser um número inteiro e finito de "coisas".

    Mas fizeste bem em esclarecer.
     
  12. hgo69

    hgo69 Power Member

    Nao vou por a linguagem exacta mas ca vai a teoria.


    Código:
    scanf("%d",n);
    
    while(n>=1)
    {
    i++;
    n=n/10
    }
    
    printf("%d", i);

    penso ser assim, nao tenho o c no pc por isso n posso testar, mas penso que seja assim.
    espero ter ajudado
    cumpz
     
    Última edição pelo moderador: 7 de Setembro de 2008
  13. syMMys

    syMMys Banido

    O algortimo do logaritmo é complexo e certamente que os casts são o menos importante.

    A história com a string é apenas uma curiosidade.

    O algoritmo onde se vai sucessivamente dividindo o inteiro por 10 é o menos pesado e mais "natural". As operações mais pesadas vão ser os DIV/IDIV (x86) que comparado com o resto são gotinhas.
    Se quiseres optimizar o teu algoritmo opta por um método de busca mais inteligente. O código é simples. Se quiseres fazê-lo como exercício a ideia é:

    Imagina que sabes que o teu inteiro não tem mais do 8 algarismos

    supõe que o inteiro a sondar é o 00234142 (meti zeros à esquerda para lembrar que admitimos que o limite é de 8 algarismos)
    ora este número tem 6 algarismos. Um algoritmo diferente seria...
    Divides (divisão inteira) primeiro 10^4 (10000), se for zero o número tem menos de 4 algarimos, se for diferente de zero tem mais. No exemplo caso a divisão não seria zero logo saberiamos que tem mais de 4 algarismos. Em seguida divides o resultado da divisão anterior por 10^2 e seguirias a mesma lógica. Nesta segunda divisão o resultado seria zero logo ficarias a saber que o inteiro tem menos de 7 e mais de 4. Em seguida pegas no resto e continuas o raciocínio com uma divisão por 10^1. Se o resultado for zero então o número teria 5 algarismos, se for diferente de zero então é porque o número inteiro original tem 6 algarismos.

    Se o número máximo de algarismos for por exemplo 16, só terás de dividir em qq dos casos por 10^8, 10^4, 10^2, 10^1, ou seja, Log2(número de algarismos) divisões
     
    Última edição: 7 de Setembro de 2008
  14. Feiticeiro

    Feiticeiro Power Member

    Bastava converter o inteiro para string, e depois obter o length. Cria uma função que depois faz o return do resultado.
     
  15. hgo69

    hgo69 Power Member

    que volta!!!

    alguém já experimentou a minha maneira?? penso que esteja correcta, e sem funções, torna um pouco mais rápido o processamento
     
  16. Mavors

    Mavors Power Member

    Eu tb acho que esta é a maneira mais fácil.
     
  17. Kayvlim

    Kayvlim Undefined Moderator
    Staff Member

    Crio que neste momento a pergunta que se coloca é: quer-se a forma mais fácil ou a mais optimizada?
     
  18. syMMys

    syMMys Banido

    Convinha ler os posts anteriores. Já foi avançada essa solução e dito por um membro que:

    Obviamente que dá para fazer como indicas mas deve ser umas 100x mais lento que, por exemplo, as divisões inteiras por 10
    Se o que é pretendido é algo simples e fácil de programar sem qq relevância para a rapidez do método então encontras igualmente uns posts atrás outra solução trivial:


    Podes ir a pé até Madrid mas de carro é melhor.
     
    Última edição: 7 de Setembro de 2008
  19. The_True_Eue

    The_True_Eue Power Member

    Já tou a ver muita gente que não lê os posts anteriores...

    E que tal a solução mais estúpida de todas?

    Código:
    int dgtlen(int n)
    {
        if(n<0) n = -n;
        return n<10?1:
                 n<100?2:
                 n<1000?3:
                 n<10000?4:
                 n<100000?5:
                 n<1000000?6:
                 n<10000000?7:
                 n<100000000?8:
                 n<1000000000?9:
                 10;
    }
    
    Não é tão elegante, mas de certeza que é a mais eficiente...:002:
     
  20. zgruli

    zgruli Power Member

    The_True_Eue podes explicar este return? É que sou noob e nunca vi nada assim. :)

    Funciona como? Como um if/else?
     

Partilhar esta Página