Como é que no seguinte snippet
int a = 7;
int b = 3;
double c = 0;
c = a / b;
c
acaba tendo o valor 2, em vez de 2,3333, como seria de esperar. Se a
e b
forem duplos, a resposta muda para 2.333. Mas certamente porque c
já é um duplo deveria ter funcionado com inteiros?
Então, por int/int=double
que não funciona?
c++
variables
double
integer-division
Jahoe
fonte
fonte
Respostas:
Isso ocorre porque você está usando a versão de divisão inteira de
operator/
, que leva 2 seint
retorna umint
. Para usar adouble
versão, que retorna adouble
, pelo menos um dosint
s deve ser convertido explicitamente em adouble
.fonte
a
eb
paradouble
simplesmente para maior clareza, mas realmente não importa.static_cast<>
sempre pareceu prolixo para mim. No caso de primitivos, não há realmente nenhum perigo de confusãostatic_cast<>
ereinterpret_cast<>
confusão.static_cast
neste caso e usar elenco de estilo C. Não há nenhum benefício em usar casts de estilo C ++ aqui e eles bagunçam o código muito mais do que casts de estilo C. O elenco aritmético é exatamente o contexto em que os elencos no estilo C são perfeitamente apropriados e, na verdade, mais apropriados do que outros elencos.double(b)
. Eles nem sempre percebem que é uma conversão, uma vez que se parece com uma chamada explícita do construtor.Aqui está:
a) Dividir dois
int
s executa sempre a divisão inteira. Portanto, o resultado dea/b
no seu caso só pode ser umint
.Se você deseja manter
a
eb
comoint
s, ainda dividi-los totalmente, você deve lançar pelo menos um deles para dobrar:(double)a/b
oua/(double)b
ou(double)a/(double)b
.b)
c
é adouble
, para que possa aceitar umint
valor na atribuição: oint
é automaticamente convertido paradouble
e atribuído ac
.c) Lembre-se de que na atribuição, a expressão à direita de
=
é calculada primeiro (de acordo com a regra (a) acima, e sem levar em conta a variável à esquerda de=
) e, em seguida, atribuída à variável à esquerda de=
(de acordo com ( b) acima). Eu acredito que isso completa o quadro.fonte
Com muito poucas exceções (só consigo pensar em uma), C ++ determina todo o significado de uma expressão (ou subexpressão) a partir da própria expressão. O que você faz com os resultados da expressão não importa. No seu caso, na expressão
a / b
, não há umdouble
à vista; tudo éint
. Portanto, o compilador usa divisão inteira. Somente depois de obter o resultado, ele considera o que fazer com ele e o converte emdouble
.fonte
&funcname
depende do tipo para o qual você o converte.c
é umadouble
variável, mas o valor que está sendo atribuído a ela é umint
valor porque resulta da divisão de doisint
s, o que dá a você "divisão inteira" (descartando o restante). Então, o que acontece na linhac=a/b
éa/b
é avaliado, criando um temporário do tipoint
c
após a conversão em tipodouble
.O valor de
a/b
é determinado sem referência ao seu contexto (atribuição adouble
).fonte
Ao dividir dois números inteiros, o resultado será um número inteiro, independentemente do fato de você armazená-lo em um duplo.
fonte
Na linguagem C ++, o resultado da subexpressão nunca é afetado pelo contexto circundante (com algumas raras exceções). Este é um dos princípios que a linguagem segue cuidadosamente. A expressão
c = a / b
contém uma subexpressão independentea / b
, que é interpretada independentemente de qualquer coisa fora dessa subexpressão. O idioma não se importa se mais tarde você atribuirá o resultado a adouble
.a / b
é uma divisão inteira. Qualquer outra coisa não importa. Você verá este princípio seguido em muitos aspectos da especificação da linguagem. É assim que C ++ (e C) funciona.Um exemplo de exceção que mencionei acima é a atribuição / inicialização do ponteiro de função em situações com sobrecarga de função
Este é um contexto em que o lado esquerdo de uma atribuição / inicialização afeta o comportamento do lado direito. (Além disso, a inicialização de referência a array evita o decaimento do tipo array, que é outro exemplo de comportamento semelhante.) Em todos os outros casos, o lado direito ignora completamente o lado esquerdo.
fonte
O
/
operador pode ser usado para divisão inteira ou divisão de ponto flutuante. Você está dando a ele dois operandos inteiros, então ele está fazendo a divisão de inteiros e o resultado está sendo armazenado em um duplo.fonte
Isso é tecnicamente dependente do idioma, mas quase todos os idiomas tratam esse assunto da mesma forma. Quando há uma incompatibilidade de tipo entre dois tipos de dados em uma expressão, a maioria das linguagens tentará converter os dados em um lado do
=
para corresponder aos dados do outro lado de acordo com um conjunto de regras predefinidas.Ao dividir dois números do mesmo tipo (inteiros, duplos, etc.), o resultado será sempre do mesmo tipo (então 'int / int' sempre resultará em int).
Neste caso, você tem o
double var = integer result
que converte o resultado inteiro em um dobro após o cálculo , caso em que os dados fracionários já estão perdidos. (a maioria dos idiomas fará essa conversão para evitar imprecisões de tipo sem gerar uma exceção ou erro).Se você gostaria de manter o resultado como um dobro, você vai querer criar uma situação em que tenha
double var = double result
A maneira mais fácil de fazer isso é forçar a expressão do lado direito de uma equação para dobrar:
c = a/(double)b
A divisão entre um inteiro e um duplo resultará na conversão do inteiro para o duplo (observe que, ao fazer matemática, o compilador freqüentemente fará um "upcast" para o tipo de dados mais específico para evitar a perda de dados).
Após o upcast,
a
terminará como um duplo e agora você tem divisão entre dois duplos. Isso criará a divisão e atribuição desejadas.NOVAMENTE, observe que isso é específico da linguagem (e pode até ser específico do compilador), no entanto, quase todas as linguagens (certamente todas as que eu consigo pensar de início) tratam esse exemplo de forma idêntica.
fonte
O importante é que um dos elementos do cálculo seja do tipo float-double. Então, para obter um resultado duplo, você precisa lançar este elemento como mostrado abaixo:
ou c = a / static_cast (b);
Ou você pode criá-lo diretamente ::
Observe que um dos elementos de cálculo deve ter '.0' para indicar uma divisão de um tipo float-double por um inteiro. Caso contrário, apesar da variável c ser dupla, o resultado também será zero.
fonte