Exemplo:
float timeRemaining = 0.58f;
Por que é f
obrigatório no final deste número?
c#
floating-point
Thomas
fonte
fonte
double
.double & int
.Respostas:
Sua declaração de um float contém duas partes:
timeRemaining
é do tipofloat
.0.58
a esta variável.O problema ocorre na parte 2.
O lado direito é avaliado por conta própria. De acordo com a especificação C #, um número contendo uma vírgula decimal que não possui um sufixo é interpretado como um
double
.Portanto, agora temos um
double
valor que queremos atribuir a uma variável do tipofloat
. Para fazer isso, deve haver uma conversão implícita dedouble
parafloat
. Não existe essa conversão, porque você pode (e neste caso perder) perder informações na conversão.O motivo é que o valor usado pelo compilador não é realmente 0,58, mas o valor de ponto flutuante mais próximo de 0,58, que é 0,57999999999999978655962351581366 ... para
double
e exatamente 0,579999946057796478271484375 parafloat
.Estritamente falando,
f
não é necessário. Você pode evitar ter que usar of
sufixo convertendo o valor para umfloat
:float timeRemaining = (float)0.58;
fonte
(float) 0.58
funcionar? Você disse anteriormente que não há conversão, porque informações podem ser perdidas, então como o elenco vai funcionar?2.4
é interpretada como um duplo em qualquer outro lugar. 2. Conversões de estreitamento implícitas (como de duplo para flutuante) não são permitidas. Se você deseja abrir uma exceção a essas regras, deve ter um bom motivo. Salvar 1 toque de tecla provavelmente não será suficiente.Porque existem vários tipos numéricos que o compilador pode usar para representar o valor
0.58
:float
,double
edecimal
. A menos que você esteja OK com o compilador escolhendo um para você, você tem que desambiguar.A documentação para
double
afirma que, se você não especificar o tipo, o compilador sempre selecionadouble
como o tipo de qualquer literal numérico real:Anexar o sufixo
f
cria umfloat
; o sufixod
cria umdouble
; o sufixom
cria umdecimal
. Todos esses também funcionam em maiúsculas.No entanto, isso ainda não é suficiente para explicar por que isso não compila:
float timeRemaining = 0.58;
A metade que falta na resposta é que a conversão de em
double
0.58
parafloat
timeRemaining
potencialmente perde informações, portanto, o compilador se recusa a aplicá-las implicitamente. Se você adicionar uma conversão explícita, a conversão será executada; se você adicionar of
sufixo, nenhuma conversão será necessária. Em ambos os casos, o código seria compilado.fonte
int
e outra paradouble
.double a = 0.69f;
?float
paradouble
.O problema é que o .NET, para permitir que alguns tipos de operações implícitas sejam realizadas envolvendo
float
edouble
, precisava especificar explicitamente o que deveria acontecer em todos os cenários envolvendo operandos mistos ou então permitir conversões implícitas entre os tipos a serem realizadas em um direção apenas; A Microsoft escolheu seguir o exemplo de Java ao permitir a direção que ocasionalmente favorece a precisão, mas freqüentemente sacrifica a correção e geralmente cria problemas.Em quase todos os casos, pegar o
double
valor que está mais próximo de uma determinada quantidade numérica e atribuí-lo a afloat
produzirá ofloat
valor que está mais próximo dessa mesma quantidade. Existem alguns casos esquivos, como o valor 9.007.199.791.611.905; a melhorfloat
representação seria 9.007.200.328.482.816 (que está fora por 536.870.911), mas lançando a melhordouble
representação (ou seja, 9.007.199.791.611.904) parafloat
rendimentos 9.007.199.254.740.992 (que está fora por 536.870.913). Em geral, porém, converter a melhordouble
representação de alguma quantidade emfloat
produzirá a melhorfloat
representação possível ou uma das duas representações que são essencialmente igualmente boas.Observe que esse comportamento desejável se aplica mesmo aos extremos; por exemplo, a melhor
float
representação para a quantidade 10 ^ 308 corresponde àfloat
representação obtida ao converter a melhordouble
representação dessa quantidade. Da mesma forma, a melhorfloat
representação de 10 ^ 309 corresponde àfloat
representação alcançada ao converter a melhordouble
representação dessa quantidade.Infelizmente, as conversões na direção que não exige um elenco explícito raramente são tão precisas. Converter a melhor
float
representação de um valor emdouble
raramente produzirá algo particularmente próximo à melhordouble
representação desse valor e, em alguns casos, o resultado pode estar errado por centenas de ordens de magnitude (por exemplo, converter a melhorfloat
representação de 10 ^ 40 emdouble
resultará um valor comparável maior do que a melhordouble
representação de 10 ^ 300.Infelizmente, as regras de conversão são o que são, então é preciso conviver com o uso de typecasts e sufixos bobos ao converter valores na direção "segura", e ter cuidado com as typecasts implícitas na direção perigosa que freqüentemente produzirá resultados falsos.
fonte