Seria útil saber se você queria arredondar para o int mais próximo ou simplesmente colocar os números depois do decimal (ou seja: sempre arredondado para baixo)
Dinah
128
Sinceramente, não vejo sentido em fazer uma votação negativa de perguntas genuínas. Sim, a resposta poderia ser encontrada no Google, mas isso não melhoraria apenas a qualidade do site se as pessoas parassem de fechar cada segunda pergunta? não é como esta questão é spam ou qualquer coisa, e eu tenho certeza que seria útil para muitos de recém-chegado para c #
jay_t55
Respostas:
268
Use a Convert.ToInt32partir mscorlibde
decimalvalue=3.14m;int n =Convert.ToInt32(value);
Veja MSDN . Você também pode usar Decimal.ToInt32. Mais uma vez, consulte MSDN . Finalmente, você pode fazer um elenco direto como em
decimalvalue=3.14m;int n =(int)value;
que usa o operador de conversão explícito. Veja MSDN .
Cuidado: o Convert possui um comportamento surpreendente para determinadas conversões ( nullvs. 0vs. ""). Eu recomendo não usar Convert a menos que você realmente precisa sua flexibilidade (ou seja, em cenários de tipagem dinâmica)
Eamon Nerbonne
1
-1, pois isso não funcionará para valores como decimal.MaxValue e decimal.MinValue e resulta em um OverflowException. Acredito que @Will fornece uma resposta melhor aqui stackoverflow.com/a/501165/39532
mezoid
8
Tenha cuidado, porque Convert.ToInt32e Decimal.ToInt32se comportam de forma diferente. Do MSDN: Decimal.ToInt32- O valor de retorno é a parte integrante do valor decimal; dígitos fracionários são truncados . Convert.ToInt32- Valor de retorno arredondado para o número inteiro assinado de 32 bits mais próximo. Se o valor estiver na metade do caminho entre dois números inteiros, o número par será retornado; isto é, 4,5 é convertido em 4 e 5.5 é convertido para 6.
vezucci
67
Você não pode.
Bem, é claro que você poderia , no entanto, um int (System.Int32) não é grande o suficiente para armazenar todos os valores decimais possíveis.
Isso significa que, se você converter um decimal maior que int.MaxValue, você excederá o limite e se o decimal for menor que int.MinValue, ele ficará insuficiente.
O que acontece quando você está sobrecarregado? Uma de duas coisas. Se sua construção estiver desmarcada (ou seja, o CLR não se importa se você o fizer), seu aplicativo continuará após o valor exceder / exceder o fluxo, mas o valor no int não será o que você esperava. Isso pode levar a erros intermitentes e pode ser difícil de corrigir. Você terminará seu aplicativo em um estado desconhecido, o que pode resultar em seu aplicativo corrompendo quaisquer dados importantes em que ele esteja trabalhando. Não é bom.
Se sua montagem estiver marcada (propriedades-> compilar-> avançado-> verificar se há aritmética de estouro / estouro ou opção de compilador / marcada), seu código lançará uma exceção quando ocorrer um estouro / estouro. Provavelmente é melhor do que não; no entanto, o padrão para montagens não é verificar se há excesso / vazão.
A verdadeira questão é "o que você está tentando fazer?" Sem conhecer seus requisitos, ninguém pode lhe dizer o que você deve fazer neste caso, além do óbvio: NÃO O FAÇA.
Se você NÃO se importa especificamente, as respostas aqui são válidas. No entanto, você deve comunicar seu entendimento de que um estouro pode ocorrer e que isso não importa, envolvendo seu código de conversão em um bloco não verificado
unchecked{// do your conversions that may underflow/overflow here}
Dessa forma, as pessoas que estão atrás de você entendem que você não se importa e, no futuro, alguém alterar suas compilações para / verificadas, seu código não será interrompido inesperadamente.
Se tudo o que você deseja fazer é soltar a parte fracionária do número, deixando a parte integral, você pode usar Math.Truncate.
decimal actual =10.5M;decimal expected =10M;Assert.AreEqual(expected,Math.Truncate(actual));
Embora eu suspeite que eles sejam a mesma coisa se a entrada for decimal, me sinto mais confortável usando Decimal.Truncate do que Math.Truncate, pois o último também aceita dobras e, portanto, pode ser entendido como capaz de truncar números pares que não são a base 10, ao contrário de Decimal.Truncate, que é um verdadeiro truncamento de um número base 10.
24710 Brian Brian
7
Contextos não verificados não se aplicam a decimais; operações decimais lançam OverflowExceptions independentemente.
Dave
46
int i =(int)d;
lhe dará o número arredondado para baixo.
Se você quiser arredondar para o número par mais próximo (por exemplo,> 0,5 arredondará para cima), poderá usar
int i =(int)Math.Round(d,MidpointRounding.ToEven);
Em geral, você pode converter entre todos os tipos numéricos em C #. Se não houver informações que serão perdidas durante o elenco, você poderá fazê-las implicitamente:
int i =10;decimal d = i;
embora você ainda possa fazê-lo explicitamente se desejar:
int i =10;decimal d =(decimal)i;
No entanto, se você estiver perdendo informações através do elenco, deve fazê-lo explicitamente (para mostrar que está ciente de que pode estar perdendo informações):
decimal d =10.5M;int i =(int)d;
Aqui você está perdendo o ".5". Isso pode ser bom, mas você deve ser explícito e fazer uma conversão explícita para mostrar que sabe que pode estar perdendo as informações.
Na verdade, você deseja que MidpointRounding.AwayFromZero se você quiser que * * seja sempre arredondado com base na minha experiência de experimentar o código acima, analisando exemplos de saída aqui: msdn.microsoft.com/en-us/library/…
Elijah Lofgren
@ElijahLofgren Depende um pouco: se você está fazendo estatísticas, ToEvendeve evitar desvios estatísticos. Se você, no entanto, opera com itens ou dinheiro a pagar, AwayFromZeroparece ser a escolha certa.
Na documentação : "Esta API suporta a infraestrutura do .NET Framework e não se destina a ser usada diretamente no seu código". Por que não usar Convert.ToInt32?
H.Wolper
7
Um bom truque para o arredondamento rápido é adicionar 0,5 antes de converter o decimal em int.
Por que se preocupar em fazer isso quando há Math.Floor e Math.Ceiling?
Badaró
Na época, eu era relativamente novo em C # e, por algum motivo, não sabia que essas funções existiam. Na verdade, é um truque que aprendi no C / C ++, onde obviamente era mais útil.
Observe que todos eles retornam Decimal também - como o Decimal possui um intervalo maior de valores que um Int32, você ainda precisará converter (e verificar se há estouro / estouro).
Acho que o operador de conversão não funciona se você tiver um decimal em caixa (ou seja, um valor decimal dentro de um tipo de objeto). Convert.ToInt32 (decimal como objeto) funciona bem nesse caso.
Essa situação surge ao recuperar valores de IDENTITY / AUTONUMBER do banco de dados:
SqlCommand foo =newSqlCommand("INSERT INTO...; SELECT SCOPE_IDENTITY()", conn);int ID =Convert.ToInt32(foo.ExecuteScalar());// worksint ID =(int)foo.ExecuteScalar();// throws InvalidCastException
Adicionando mais para referência: isso é porque você pode unbox apenas para o mesmo tipo de original. Aqui SELECT SCOPE_IDENTITY()retorna numeric(38, 0)que é traduzido decimalpelo .NET. foo.ExecuteScalar()retorna uma decimalcaixa como a objectqual não pode ser convertida diretamente para uma int. (int)(decimal)foo.ExecuteScalar()ou Convert.ToInt32(foo.ExecuteScalar())iria funcionar.
Rageit # 9/14
0
Nenhuma resposta parece lidar com a OverflowException / UnderflowException que vem da tentativa de converter um decimal que está fora do intervalo de int.
int intValue =(int)Math.Max(int.MinValue,Math.Min(int.MaxValue, decimalValue));
Esta solução retornará o valor int máximo ou mínimo possível se o valor decimal estiver fora do intervalo int. Você pode adicionar alguns arredondamentos com Math.Round, Math.Ceiling ou Math.Floor para quando o valor estiver dentro do intervalo int.
Respostas:
Use a
Convert.ToInt32
partirmscorlib
deVeja MSDN . Você também pode usar
Decimal.ToInt32
. Mais uma vez, consulte MSDN . Finalmente, você pode fazer um elenco direto como emque usa o operador de conversão explícito. Veja MSDN .
fonte
null
vs.0
vs.""
). Eu recomendo não usar Convert a menos que você realmente precisa sua flexibilidade (ou seja, em cenários de tipagem dinâmica)OverflowException
. Acredito que @Will fornece uma resposta melhor aqui stackoverflow.com/a/501165/39532Convert.ToInt32
eDecimal.ToInt32
se comportam de forma diferente. Do MSDN:Decimal.ToInt32
- O valor de retorno é a parte integrante do valor decimal; dígitos fracionários são truncados .Convert.ToInt32
- Valor de retorno arredondado para o número inteiro assinado de 32 bits mais próximo. Se o valor estiver na metade do caminho entre dois números inteiros, o número par será retornado; isto é, 4,5 é convertido em 4 e 5.5 é convertido para 6.Você não pode.
Bem, é claro que você poderia , no entanto, um int (System.Int32) não é grande o suficiente para armazenar todos os valores decimais possíveis.
Isso significa que, se você converter um decimal maior que int.MaxValue, você excederá o limite e se o decimal for menor que int.MinValue, ele ficará insuficiente.
O que acontece quando você está sobrecarregado? Uma de duas coisas. Se sua construção estiver desmarcada (ou seja, o CLR não se importa se você o fizer), seu aplicativo continuará após o valor exceder / exceder o fluxo, mas o valor no int não será o que você esperava. Isso pode levar a erros intermitentes e pode ser difícil de corrigir. Você terminará seu aplicativo em um estado desconhecido, o que pode resultar em seu aplicativo corrompendo quaisquer dados importantes em que ele esteja trabalhando. Não é bom.
Se sua montagem estiver marcada (propriedades-> compilar-> avançado-> verificar se há aritmética de estouro / estouro ou opção de compilador / marcada), seu código lançará uma exceção quando ocorrer um estouro / estouro. Provavelmente é melhor do que não; no entanto, o padrão para montagens não é verificar se há excesso / vazão.
A verdadeira questão é "o que você está tentando fazer?" Sem conhecer seus requisitos, ninguém pode lhe dizer o que você deve fazer neste caso, além do óbvio: NÃO O FAÇA.
Se você NÃO se importa especificamente, as respostas aqui são válidas. No entanto, você deve comunicar seu entendimento de que um estouro pode ocorrer e que isso não importa, envolvendo seu código de conversão em um bloco não verificado
Dessa forma, as pessoas que estão atrás de você entendem que você não se importa e, no futuro, alguém alterar suas compilações para / verificadas, seu código não será interrompido inesperadamente.
Se tudo o que você deseja fazer é soltar a parte fracionária do número, deixando a parte integral, você pode usar Math.Truncate.
fonte
lhe dará o número arredondado para baixo.
Se você quiser arredondar para o número par mais próximo (por exemplo,> 0,5 arredondará para cima), poderá usar
Em geral, você pode converter entre todos os tipos numéricos em C #. Se não houver informações que serão perdidas durante o elenco, você poderá fazê-las implicitamente:
embora você ainda possa fazê-lo explicitamente se desejar:
No entanto, se você estiver perdendo informações através do elenco, deve fazê-lo explicitamente (para mostrar que está ciente de que pode estar perdendo informações):
Aqui você está perdendo o ".5". Isso pode ser bom, mas você deve ser explícito e fazer uma conversão explícita para mostrar que sabe que pode estar perdendo as informações.
fonte
ToEven
deve evitar desvios estatísticos. Se você, no entanto, opera com itens ou dinheiro a pagar,AwayFromZero
parece ser a escolha certa.Isso deve funcionar muito bem.
fonte
Aqui está uma página da Web de tipo de dados de conversão muito útil para as de outras pessoas. http://www.convertdatatypes.com/Convert-decimal-to-int-in-CSharp.html
fonte
System.Decimal
implementa aIConvertable
interface, que possui umToInt32()
membro.A chamada
System.Decimal.ToInt32()
funciona para você?fonte
Um bom truque para o arredondamento rápido é adicionar 0,5 antes de converter o decimal em int.
Ainda sai
i=10
, masArredondaria para que
i=11
.fonte
Prefiro usar Math.Round , Math.Floor , Math.Ceiling ou Math.Truncate para definir explicitamente o modo de arredondamento conforme apropriado.
Observe que todos eles retornam Decimal também - como o Decimal possui um intervalo maior de valores que um Int32, você ainda precisará converter (e verificar se há estouro / estouro).
fonte
decimal
d = 5.5
;ref: texto do link
fonte
Arredondando um decimal para o número inteiro mais próximo
quando
a = 49.9
entãob = 50
quando
a = 49.5
entãob = 50
quando
a = 49.4
, entãob = 49
etc.fonte
Acho que o operador de conversão não funciona se você tiver um decimal em caixa (ou seja, um valor decimal dentro de um tipo de objeto). Convert.ToInt32 (decimal como objeto) funciona bem nesse caso.
Essa situação surge ao recuperar valores de IDENTITY / AUTONUMBER do banco de dados:
Consulte 4.3.2 Conversões de unboxing
fonte
SELECT SCOPE_IDENTITY()
retornanumeric(38, 0)
que é traduzidodecimal
pelo .NET.foo.ExecuteScalar()
retorna umadecimal
caixa como aobject
qual não pode ser convertida diretamente para umaint
.(int)(decimal)foo.ExecuteScalar()
ouConvert.ToInt32(foo.ExecuteScalar())
iria funcionar.Nenhuma resposta parece lidar com a OverflowException / UnderflowException que vem da tentativa de converter um decimal que está fora do intervalo de int.
Esta solução retornará o valor int máximo ou mínimo possível se o valor decimal estiver fora do intervalo int. Você pode adicionar alguns arredondamentos com Math.Round, Math.Ceiling ou Math.Floor para quando o valor estiver dentro do intervalo int.
fonte