terça-feira, julho 01, 2008

Obter a parte decimal em c#

Por acaso nunca tinha necessitado mas pensava que existiria algo de framework que nos possibilitasse obter a parte decimal de um double. Bem aparentemente não existe nada, e o que encontrei na net achei um pouco complexo demais para a simplicidade do problema em si, logo fiz eu o seguinte código que acho não ser nada complicado e funciona em todas as situações (pelo menos as que testei).

public static int GetDecimalPart(double value)
{
  int number = (int) value;
  string numbString = number.ToString();
  int stringLength = numbString.Length;
  return Int32.Parse(value.ToString().Substring(stringLength+1));
}

9 comentários:

  1. Não funciona se a parte decimal do double, depois de convertida, exceder a capacidade do int.

    ResponderEliminar
  2. esquece o comentario anterior queres a parte decimal e n a inteira

    ResponderEliminar
  3. Se o int não chegar podes sempre por um long :P
    Isso é como tudo, se as tuas roupas não couberem no teu roupeiro tens de comprar um maior!

    ResponderEliminar
  4. (nao é c#, mas deve ter uma função análoga)

    return value - Math.floor(value);

    ResponderEliminar
  5. Olá Tiago,

    assim muito em cima do joelho, olha para os resultados deste código:
    class Program
    {
    static void Main(string[] args)
    {
    double value = 1.123456789;
    DateTime start = DateTime.UtcNow;
    for (int i = 0; i < 10000; i++)
    {
    GetDecimalPartUsingDecimal(value);
    }
    Console.WriteLine(DateTime.UtcNow - start);


    start = DateTime.UtcNow;
    for (int i = 0; i < 10000; i++)
    {
    GetDecimalPartUsingMod(value);
    }
    Console.WriteLine(DateTime.UtcNow - start);

    start = DateTime.UtcNow;
    for (int i = 0; i < 10000; i++)
    {
    GetDecimalPartUsingString(value);
    }
    Console.WriteLine(DateTime.UtcNow - start);
    Console.ReadLine();

    }


    private static decimal GetDecimalPartUsingDecimal(double value)
    {
    decimal myValuePrecision = Convert.ToDecimal(value);
    return myValuePrecision - myValuePrecision - Decimal.Truncate(myValuePrecision);

    }

    private static double GetDecimalPartUsingMod(double value)
    {
    return value % 1;

    }

    public static int GetDecimalPartUsingString(double value)
    {
    int number = (int)value;
    string numbString = number.ToString();
    int stringLength = numbString.Length;
    return Int32.Parse(value.ToString().Substring(stringLength + 1));
    }
    }

    ResponderEliminar
  6. Para o André, o que eu quero é obter a parte decimal de um número só, para o número 1.123456789 eu quero como resultado 123456789 e não 0.123456789.

    Para o Hugo, a tua 1ª função tinha um errinho mas eu percebi no return deveria estar myValuePrecision - Decimal.Truncate(myValuePrecision); e mais uma vez o teu resultado é igual ao do André apesar de demorar 1/3 do tempo da minha função.
    Na 2ª função a nível de tempo é instantânea mas cuidado com o resultado que não é bem igual ao da 1ª função, se na 1ª obtinhas 0.123456789 aqui apanhas com os erros dos arredondamentos dos valores decimais e obtens 0.12345678900000001.
    A 3ª função que é a minha retorna-me exactamente o que eu quero que foi o que expliquei ao André.
    Já agora aumentei as iterações para 100000 e os resultados que obtive em ticks foram:
    1ª - 781250
    2ª - 0
    3ª - 2343750

    ResponderEliminar
  7. Olá Tiago,

    Tira-me só uma dúvida, pelo teu código, a parte decimal de 1.02 será igual à parte decimal de 1.2...?

    Abraços!

    ResponderEliminar
  8. Sim sr. uma dúvida bastante inteligente :)
    Eu à primeira diria que era 2 porque seria Int32.Parse("02");
    Realmente já começo a perceber agora porque esta função não existe de framework, porque nestes casos o resultado é um pouco tricky(resultado 2 poderia ter como origem ,2 ,02 ,002...).
    Contudo para as minhas necessidades não havia problema porque o meu primeiro digito decimal nunca era 0.

    ResponderEliminar