Convertendo um duplo em um int em C #


103

Em nosso código, temos um duplo que precisamos converter em um int.

double score = 8.6;
int i1 = Convert.ToInt32(score);
int i2 = (int)score;

Alguém pode me explicar por quê i1 != i2?

O resultado que obtenho é: i1 = 9e i2 = 8.


5
Math.Truncate(score)é intenção expressa mais explicitamente do que(int)score
Lu55

3
Mas Math.Truncate retorna um duplo ou decimal, não um int
Sergioet

Respostas:


164

Porque Convert.ToInt32rondas:

Valor de retorno: arredondado para o 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; ou seja, 4,5 é convertido em 4 e 5,5 é convertido em 6.

... enquanto o elenco trunca :

Quando você converte de um valor duplo ou flutuante em um tipo integral, o valor é truncado.

Atualização: Veja o comentário de Jeppe Stig Nielsen abaixo para diferenças adicionais (que, entretanto, não entram em jogo se scorefor um número real como é o caso aqui).


6
Na verdade, seu link explica melhor, e não é tão simples quanto round vs truncate: Tipo: System.Int32 value, arredondado para o 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; ou seja, 4,5 é convertido em 4 e 5,5 é convertido em 6.
ericosg

@ericosg: Sim, isso iria mascarar a diferença se scorefosse 8.5em vez de 8.6. Eu atualizei a resposta para incluir as aspas. Obrigado pela contribuição.
Jon

5
E se scorefor NaNou infinito ou finito, mas fora do intervalo de Int32, Convert.ToInt32lançará uma exceção. O elenco retornará um int, mas você não saberá qual (na minha implementação é Int32.MinValue) porque você está emunchecked contexto. (Se você estiver no checkedcontexto, o elenco também lançará uma exceção nesses casos.)
Jeppe Stig Nielsen

@JeppeStigNielsen: Obrigado pela contribuição, atualizei a resposta para mencionar isso também.
Jon

Agradável. Mas eu acho queDouble número tipo 10000000000.6(dez bilhões vírgula seis) é um número "real". Usar um elenco para intisso dará um resultado estranho (a menos que você esteja no checkedcontexto, mas provavelmente não está).
Jeppe Stig Nielsen

13

A conversão irá ignorar qualquer coisa após a vírgula decimal, então 8,6 se torna 8.

Convert.ToInt32(8.6) é a maneira segura de garantir que seu duplo seja arredondado para o número inteiro mais próximo, neste caso, 9.


1
Pergunta bônus - o que acontece se o valor do dobro for muito grande para empurrar para o int ? Ou seja, se for maior do que int.MAX_VAL ?
Konrad Viltersten

1
@KonradViltersten Lança uma exceção O valor era muito grande ou muito pequeno para um Int32.
Vamsi de

11

você pode arredondar seu duplo e elenco:

(int)Math.Round(myDouble);

4
a questão agora era como fazer i1 == i2. A questão era por que eles não são iguais. Votos negativos.
Adam

5

No exemplo fornecido, seu decimal é 8,6 . Se fosse 8,5 ou 9,5, a afirmação i1 == i2 poderia ser verdadeira. De fato, seria verdadeiro para 8,5 e falso para 9,5.

Explicação:

Independentemente da parte decimal, a segunda declaração, int i2 = (int)score descartará a parte decimal e simplesmente retornará a parte inteira. Uma coisa muito perigosa de se fazer, pois pode ocorrer perda de dados.

Agora, para a primeira declaração, duas coisas podem acontecer. Se a parte decimal for 5, ou seja, está no meio, uma decisão deve ser tomada. Nós arredondamos para cima ou para baixo? Em C #, a classe Convert implementa o arredondamento do banqueiro. Veja isso resposta para uma explicação mais detalhada. Simplificando, se o número for par, arredonde para baixo; se o número for ímpar, arredonde para cima.

Por exemplo, considere:

        double score = 8.5;
        int i1 = Convert.ToInt32(score); // 8
        int i2 = (int)score;             // 8

        score += 1;
        i1 = Convert.ToInt32(score);     // 10
        i2 = (int)score;                 // 9

2

ToInt32 rounds. Casting para int apenas descarta o componente não inteiro.

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.