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

Conversor de unidades de memoria, repositório de código

Discussão em 'Programação' iniciada por Peter V5, 5 de Outubro de 2008. (Respostas: 7; Visualizações: 3682)

  1. Peter V5

    Peter V5 Folding Member

    Aqui está um programa que converte bytes ou megabyte para kilobytes ou gigabytes, por ai fora

     
  2. bsd

    bsd Power Member

    Ó pá, tava aqui a ver isto por acaso, e não me pude conter, tive de postar porque acho o teu código pouco elegante. Três coisas:

    - Usas um switch, quando uma lookup table seria mais elegante
    - Convertes tudo para bytes e depois voltas a converter, quando uma conversão só seria suficiente. Não é só mau por fazeres duas conversões, mas se se tratarem de números muito grandes podes ter um overflow desnecessário.
    - Usas muitas multiplicações e divisões quando um único shiftezinho bastava
    e permitia-te fazer código que também funcionava em inteiro

    Eis uma versão em inteiro (sem os printfs):

    Código:
    #include <assert.h>
    
    int converte(int de, int para, int quantos)
    {
        static const int unidade[5] = { 0, 10, 20, 30, 40 };
    
        assert(de >= 1 && de <= 5 && para >= 1 && para <= 5);
    
        int expoente = unidade[para - 1] - unidade[de - 1];
        return quantos << expoente;
    }
    
    Agora a versão em vírgula flutuante:

    Código:
    #include <assert.h>
    #include <math.h>
    
    double converte(int de, int para, double quantos)
    {
        static const int unidade[5] = { 0, 10, 20, 30, 40 };
    
        assert(de >= 1 && de <= 5 && para >= 1 && para <= 5);
    
        int expoente = unidade[para - 1] - unidade[de - 1];
        return ldexp(quantos, expoente);
    }
    
    Boas.
     
  3. Peter V5

    Peter V5 Folding Member

    Foste desenterrar um tópico do repositório do código para dizer que tens uma maneira melhor de fazer as coisas de uma maneira que nem conheço, muito bem mas por isso mas dai a dizer que o meu codigo está pouco elegante é que já não..
     
  4. bsd

    bsd Power Member

    Agora já conheces. Isso se calhar quer dizer que o meu post pode ser mais instrutivo e útil para alguém. A técnica que sugeri tem vantagens objectivas: só usa somas e um único shift, evita overflow desnecessário, e é fácil estender para terabytes, petabytes e etc. A técnica que tu sugeriste tem um número de linhas de código proporcional ao quadrado do número de unidades a converter.
     
  5. Peter V5

    Peter V5 Folding Member

    Ya porreiro, pena eu não conhecer a biblioteca assert.h
     
  6. bsd

    bsd Power Member

    O assert não está lá a fazer nada, não tem qualquer efeito no código. Só meti o assert porque me sentia mal a indexar um array sem verificar que o índice estava dentro dos limites.

    O header <assert.h> da biblioteca padrão do C define um macro, o assert, que serve para verificar se uma condição, que o programador pensa ser verdadeira naquele momento, é efectivamente verdadeira (as condições para as quais aquele código foi pensado). Na versão debug do código, a expressão assert(x) transforma-se em if (!(x)) abort(). Na versão release (ao definir o macro NDEBUG), a expressão assert(x) não geral qualquer código.

    Por exemplo, o código inteiro pode ficar apenas (sem recurso a qualquer função de qualquer biblioteca):

    Código:
    int converte(int de, int para, int x)
    {
        static const int unidade[5] = { 0, 10, 20, 30, 40 };
        int expoente = unidade[para - 1] - unidade[de - 1];
        return quantos << expoente;
    }
    
    A versão em vírgula flutuante utiliza, essa sim, uma função do C, o ldexp. Esta função existe porque os números são representados em sinal, expoente e mantissa, e os microprocessadores têm instruções para adicionar ao expoente. Esta função ldexp(x, y) adiciona y ao expoente de x, o que é equivalente a multiplicar x por 2 elevado a y.

    Também na versão inteiro, o shift para a esquerda é equivalente a multiplicar "quantos" por 2 elevando a "expoente".

    O código seguinte é mais fácil de entender:

    Código:
    double converte(int de, int para, double x)
    {
        static const long unidade[4] = { 1L, 1024L, 1024L*1024L, 1024L*1024L*1024L };
        return quantos * unidade[para - 1] / unidade[de - 1];
    }
    
    Há uma única multiplicação pela razão entre as duas unidades. No entanto, a versão anterior, aproveita o facto das unidades serem potências de 2 para simplesmente adicionar ao expoente (ou fazer o shift no caso inteiro), em vez de fazer uma multiplicação, o que é mais rápido.
     
  7. AragTey

    AragTey Power Member


    Recebeste aqui uma critica bem construtiva...aprender a aceita-las irá ser-te bastante util para continuares a crescer como programador.

    Gostei dos posts do bsd...tu tambem devias ter gostado.
     
  8. Peter V5

    Peter V5 Folding Member

    Peço desculpa, quando vi ver isto estava um bocado irritado com uma coisa. até foi um post porreiro.

    bsd, esplicação porreira, percebes bem disto, lol
     
    Última edição: 12 de Outubro de 2008

Partilhar esta Página