Para este bloco de código:
int num = 5;
int denom = 7;
double d = num / denom;
o valor de d
é 0.0
. Pode ser forçado a trabalhar lançando:
double d = ((double) num) / denom;
Mas existe outra maneira de obter o double
resultado correto ? Não gosto de lançar primitivos, quem sabe o que pode acontecer.
java
casting
integer-division
Walnutmon
fonte
fonte
Respostas:
Isso evita um elenco. Mas você descobrirá que as conversões de elenco são bem definidas. Você não precisa adivinhar, basta verificar o JLS . int dobrar é uma conversão crescente. A partir do §5.1.2 :
5 pode ser expresso exatamente como um duplo.
fonte
1.0
ainda altera o tipo de resultado, apenas de uma maneira diferente. "Parece código sujo para mim" não explica em que cenário (s) você acredita que multiplicar1.0
é realmente melhor (ou por que isso pode ser).(double)num
alguma maneira mudanum
. Não - ele cria um duplo temporário para o contexto da declaração.O que há de errado com a transmissão de primitivas?
Se você não quer transmitir por algum motivo, pode fazer
fonte
double d = num * 1D / denom;
Por que você tem um medo irracional de lançar primitivos? Nada de ruim vai acontecer quando você joga um
int
para umdouble
. Se você não tiver certeza de como isso funciona, consulte a Especificação de Linguagem Java . Converter umint
paradouble
é uma conversão primitiva cada vez maior .Você pode se livrar do par extra de parênteses lançando o denominador em vez do numerador:
fonte
double d = (double) num / denom;
... (OK, este depende de precedência)Se você alterar o tipo de uma das variáveis, lembre-se de esgueirar-se novamente duas vezes se sua fórmula mudar, porque se essa variável deixar de fazer parte do cálculo, o resultado será confuso. Eu tenho o hábito de transmitir dentro do cálculo e adiciono um comentário ao lado.
Observe que a transmissão do resultado não fará isso
fonte
Lance um dos números inteiros / os dois inteiros para flutuar para forçar a operação a ser feita com ponto flutuante Math. Caso contrário, o número inteiro Math é sempre preferido. Assim:
Observe que a transmissão do resultado não será suficiente. Porque a primeira divisão é feita conforme a regra de precedência.
Eu não acho que exista algum problema com o elenco, como tal, você está pensando.
fonte
Fundição tipo é a única maneira
Produzir uma
double
divisão inteira - não há outro caminho sem a conversão (pode ser que você não faça isso explicitamente, mas isso acontecerá).Agora, existem várias maneiras pelas quais podemos tentar obter um
double
valor preciso (ondenum
edenom
são doint
tipo e, é claro, com a transmissão ) -com transmissão explícita:
double d = (double) num / denom;
double d = ((double) num) / denom;
double d = num / (double) denom;
double d = (double) num / (double) denom;
mas não
double d = (double) (num / denom);
com elenco implícito:
double d = num * 1.0 / denom;
double d = num / 1d / denom;
double d = ( num + 0.0 ) / denom;
double d = num; d /= denom;
mas não
double d = num / denom * 1.0;
e não
double d = 0.0 + ( num / denom );
fonte
use algo como:
(1d é convertido para dobrar)
fonte
Você pode considerar agrupar as operações. Por exemplo:
Isso permite que você verifique (apenas uma vez) se o elenco faz exatamente o que você deseja. Esse método também pode estar sujeito a testes, para garantir que ele continue fazendo o que você deseja. Também não importa qual truque você usa para causar a divisão (você pode usar qualquer uma das respostas aqui), desde que resulte no resultado correto. Em qualquer lugar que você precisar dividir dois números inteiros, agora você pode simplesmente ligar
Utils::divide
e confiar que ele faz a coisa certa.fonte
apenas use isso.
fonte
A melhor maneira de fazer isso é
fonte