Melhor maneira de obter um número inteiro parte de um número decimal


91

Qual é a melhor maneira de retornar a parte do número inteiro de um decimal (em c #)? (Isso deve funcionar para números muito grandes que podem não caber em um int).

GetIntPart(343564564.4342) >> 343564564
GetIntPart(-323489.32) >> -323489
GetIntPart(324) >> 324

O objetivo disso é: Estou inserindo em um campo decimal (30,4) no banco de dados e quero garantir que não tento inserir um número que seja muito longo para o campo. Determinar o comprimento da parte do número inteiro do decimal faz parte desta operação.


Você não pode obter a parte interna; você pode obter a parte do número inteiro e descartar a parte fracionária. A parte do número inteiro de um Decimal pode facilmente estourar um int e jogar ou quebrar, matando silenciosamente seu código.

1
Bem, é por isso que esta questão não é tão simples quanto parece. Preciso que isso funcione para números muito grandes de maneira tão confiável quanto para números pequenos. No entanto, "número inteiro" é mais preciso do que "int" - vou reformular acima.
Yaakov Ellis

Respostas:


215

A propósito, pessoal, (int) Decimal.MaxValue irá estourar. Você não pode obter a parte "int" de um decimal porque o decimal é muito grande para ser colocado na caixa int. Acabei de verificar ... é até muito grande para um longo (Int64).

Se você quiser que o bit de um valor decimal fique à ESQUERDA do ponto, você precisa fazer o seguinte:

Math.Truncate(number)

e retorna o valor como ... A DECIMAL ou DOUBLE.

editar: Truncar é definitivamente a função correta!


Então o resultado é decimal ou duplo que nunca terá nada depois do ponto, mas não há um objeto embutido para armazenar o resultado como um "int" (sem casas decimais) que parece um pouco coxo?
Coops de

@CodeBlend: Não há muita necessidade de projetar frameworks em torno do desejo de perder precisão.

@CodeBlend: Você ainda perderia a precisão porque está cortando os valores decimais de um número. Não tenho certeza do que você quer chegar.

Não tenho certeza se isso vai funcionar ou não. Porque Math.Truncate (-5.99999999999999999) retorna -6.0 para mim ... !!
Bharat Mori

@Bharat Mori: Parece que -5.99999999999999999 é arredondado para -6,0 antes do truncamento. Tente com o sufixo "m" e funcionará. Math.Truncate (-5.99999999999999999m) dá -5.
Henry


4

Depende do que você está fazendo.

Por exemplo:

//bankers' rounding - midpoint goes to nearest even
GetIntPart(2.5) >> 2
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -6

ou

//arithmetic rounding - midpoint goes away from zero
GetIntPart(2.5) >> 3
GetIntPart(5.5) >> 6
GetIntPart(-6.5) >> -7

O padrão é sempre o primeiro, o que pode ser uma surpresa, mas faz muito sentido .

Seu elenco explícito fará:

int intPart = (int)343564564.5
// intPart will be 343564564

int intPart = (int)343564565.5
// intPart will be 343564566

Pela maneira como você formulou a pergunta, parece que não é isso o que você deseja - você sempre quer reformular.

Eu faria:

Math.Floor(Math.Abs(number));

Verifique também o tamanho dos seus decimal- eles podem ser bem grandes, então você pode precisar usar a long.


(longo) Estouros de Decimal.MaxValue.

Ponto justo - acho que é por isso que Math.Truncate (decimal) retorna decimal.
Keith

Em C #, a conversão para int não é arredondada, portanto (int) 0.6f será 0 e (int) 343564565.5 terminará em 5, não 6. Tente aqui: repl.it/repls/LuxuriousCheerfulDistributeddatabase
sschmidTU

0

Você só precisa lançá-lo, como tal:

int intPart = (int)343564564.4342

Se você ainda quiser usá-lo como um decimal em cálculos posteriores, então Math.Truncate (ou possivelmente Math.Floor se quiser um certo comportamento para números negativos) é a função desejada.


5
Isso está errado, errado, errado. Se o resultado for maior do que o que um Int32 pode conter, ele lançará uma exceção ou (pior ainda!) Silenciosamente transbordará e retornará, dando a você um resultado completamente incorreto sem que você saiba.

2
Não, não está errado . Pode não ser válido para decimais / valores de ponto flutuante muito grandes, mas é perfeitamente adequado para a maioria das situações. Os números são freqüentemente limitados para serem baixos o suficiente durante a codificação, então isso não precisa ser um problema. Além disso, forneci uma solução Math.Truncate que funciona para todos os valores.
Noldorin

2
Eu vejo porque você está chateado comigo. O fato é que sua resposta está errada. Você está dizendo a ele para se arriscar a não quebrar porque, ei, muitos números são pequenos. É um risco tolo de correr. Você deve editar sua resposta e remover tudo, exceto Math.Truncate, pois é a única parte correta.

1
Você sabe o que dizem sobre ASSUME. Além disso, sua suposição é particularmente terrível. Isso é inflamatório? Eu acho que você poderia dizer isso. Você também pode dizer que dizer a alguém para fazer algo tolo que vai causar problemas no futuro também é inflamatório, se não totalmente antiético.

1
Na verdade, isso seria errado se eu pretendesse dar uma resposta enganosa. Por assim dizer, eu estava simplesmente tentando ajudar. Se eu for culpado de um leve mal-entendido ou de não entender totalmente a questão, isso é justo - não é crime. Então, por que estamos discutindo agora? Todos concordamos que Truncate é a resposta certa.
Noldorin

0

Maneira muito fácil de separar o valor e seu valor da parte fracionária.

double  d = 3.5;
int i = (int)d;
string s = d.ToString();
s = s.Replace(i + ".", "");

s é a parte fracionária = 5
ei é o valor como inteiro = 3


1
Veja a resposta principal acima. Isso não funciona porque (int)Decimal.MaxValuevai transbordar.
Yaakov Ellis

0

Espero te ajudar.

/// <summary>
/// Get the integer part of any decimal number passed trough a string 
/// </summary>
/// <param name="decimalNumber">String passed</param>
/// <returns>teh integer part , 0 in case of error</returns>
private int GetIntPart(String decimalNumber)
{
    if(!Decimal.TryParse(decimalNumber, NumberStyles.Any , new CultureInfo("en-US"), out decimal dn))
    {
        MessageBox.Show("String " + decimalNumber + " is not in corret format", "GetIntPart", MessageBoxButtons.OK, MessageBoxIcon.Error);
        return default(int);
    } 

    return Convert.ToInt32(Decimal.Truncate(dn));
}

-2
   Public Function getWholeNumber(number As Decimal) As Integer
    Dim round = Math.Round(number, 0)
    If round > number Then
        Return round - 1
    Else
        Return round
    End If
End Function

1
A resposta aceita - postada há mais de oito anos - explica por que essa resposta está errada. O alcance de decimalé muito maior do que o de int. Além disso, esta não é uma pergunta do VB.
Joe Farrell

@JoeFarrell - se achar que a resposta está errada, você pode considerar a opção de downvoting, além de apenas deixar um comentário sobre o efeito. No entanto, não sinalize (não que eu esteja dizendo que você fez). É uma tentativa de responder à pergunta. Pode estar no idioma errado, pode estar errado até em VB, mas é uma tentativa. Veja, por exemplo, " Quando uma resposta responde à pergunta errada, não é uma resposta? ".
Wai Ha Lee
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.