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:

Anónimo disse...

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

dvnu disse...

Math.Round ?

dvnu disse...

esquece o comentario anterior queres a parte decimal e n a inteira

Tiago Sousa disse...

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!

Anónimo disse...

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

return value - Math.floor(value);

Anónimo disse...

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));
}
}

Tiago Sousa disse...

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

Anónimo disse...

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!

Tiago Sousa disse...

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.