Converter decimal em dobro

671

Eu quero usar um Track-Barpara mudar a Formopacidade de um.

Este é o meu código:

decimal trans = trackBar1.Value / 5000;
this.Opacity = trans;

Quando crio o aplicativo, ele fornece o seguinte erro:

Não é possível converter implicitamente o tipo decimalparadouble

Eu tentei usar transe, em doubleseguida, o Controlnão funciona. Esse código funcionou bem em um projeto anterior do VB.NET.

Eggs McLaren
fonte
11
Além disso, o decimal não pode representar um valor tão amplo quanto um duplo. O decimal só pode ir até +/- 7.9228162514264337593543950335E + 28; Considerando que um duplo pode ir até +/- 1.79769313486232E + 308
TraumaPony
7
Alguém deve marcar este como duplicado.
Ivan
7
@Ivan: Esta é a quarta pergunta feita no SO de todos os tempos ...
Nikolas
1
@ Nikolas: De fato. Rastreado aqui hoje.
27 de

Respostas:

446

Um elenco explícito para doubleisso não é necessário:

double trans = (double) trackBar1.Value / 5000.0;

Identificar a constante como 5000.0(ou como 5000d) é suficiente:

double trans = trackBar1.Value / 5000.0;
double trans = trackBar1.Value / 5000d;
Kevin Dente
fonte
123

Uma resposta mais genérica para a pergunta genérica "Decimal versus duplo?": Decimal para cálculos monetários para preservar a precisão, dobro para cálculos científicos que não são afetados por pequenas diferenças. Como Double é um tipo nativo da CPU (a representação interna é armazenada na base 2 ), os cálculos feitos com o Double têm melhor desempenho que o Decimal (representado na base 10 internamente).

huseyint
fonte
83

Seu código funcionou bem no VB.NET porque faz implicitamente qualquer conversão, enquanto o C # tem implícitos e explícitos.

Em C #, a conversão de decimal para duplo é explícita à medida que você perde a precisão. Por exemplo, o 1.1 não pode ser expresso com precisão como um duplo, mas como um decimal (consulte " Números de ponto flutuante - mais imprecisos do que você pensa " pelo motivo).

No VB, a conversão foi adicionada para você pelo compilador:

decimal trans = trackBar1.Value / 5000m;
this.Opacity = (double) trans;

Isso (double)precisa ser explicitamente declarado em C #, mas pode ser implícito no compilador mais 'perdoador' do VB.

Keith
fonte
80

Por que você está dividindo por 5000? Basta definir os valores Mínimo e Máximo do TrackBar entre 0 e 100 e depois dividir o Valor por 100 para a porcentagem de Opacidade. O exemplo mínimo de 20 abaixo impede que o formulário fique completamente invisível:

private void Form1_Load(object sender, System.EventArgs e)
{
    TrackBar1.Minimum = 20;
    TrackBar1.Maximum = 100;

    TrackBar1.LargeChange = 10;
    TrackBar1.SmallChange = 1;
    TrackBar1.TickFrequency = 5;
}

private void TrackBar1_Scroll(object sender, System.EventArgs e)
{
    this.Opacity = TrackBar1.Value / 100;
}
Gordon Bell
fonte
5
Isso não mudaria o problema? Em vez de um problema com 5000, o OP teria um problema com 100?
jww 22/09/14
62

Você tem dois problemas. Primeiro, Opacityrequer um valor duplo, não decimal. O compilador está lhe dizendo que, embora haja uma conversão entre decimal e dupla, é uma conversão explícita que você precisa especificar para que funcione. A segunda é que TrackBar.Valueé um valor inteiro e a divisão de um int por um int resulta em um int, independentemente do tipo de variável que você atribui a ele. Nesse caso, há uma conversão implícita de int para decimal ou dupla - porque não há perda de precisão quando você faz a conversão -, portanto, o compilador não reclama, mas o valor que você obtém é sempre 0, presumivelmente, poistrackBar.Valuesempre é menor que 5000. A solução é alterar seu código para usar double (o tipo nativo do Opacity) e fazer aritmética de ponto flutuante, tornando explicitamente a constante um double - o que terá o efeito de promover a aritmética - ou converter trackBar.Valuepara double , que fará a mesma coisa - ou ambos. Ah, e você não precisa da variável intermediária, a menos que seja usada em outro lugar. Meu palpite é que o compilador o otimizaria, de qualquer maneira.

trackBar.Opacity = (double)trackBar.Value / 5000.0;
tvanfosson
fonte
58

Na minha opinião, é desejável ser o mais explícito possível. Isso adiciona clareza ao código e ajuda seus colegas programadores que eventualmente o leem.

Além de (ou em vez de) anexar .0a ao número, você pode usar decimal.ToDouble().

aqui estão alguns exemplos:

// Example 1
double transperancy = trackBar1.Value/5000;
this.Opacity = decimal.ToDouble(transperancy);

// Example 2 - with inline temp
this.Opacity = decimal.ToDouble(trackBar1.Value/5000);
andnil
fonte
57

Parece this.Opacityum valor duplo, e o compilador não gosta de você tentar inserir um valor decimal nele.

Ryan Fox
fonte
50

A propriedade Opacity é do tipo duplo:

double trans = trackBar1.Value / 5000.0;
this.Opacity = trans;

ou simplesmente:

this.Opacity = trackBar1.Value / 5000.0;

ou:

this.Opacity = trackBar1.Value / 5000d;

Observe que estou usando 5000.0(ou 5000d) para forçar uma divisão dupla porque trackBar1.Valueé um número inteiro e ele executaria uma divisão inteira e o resultado seria um número inteiro.

Darin Dimitrov
fonte
49

Você deve usar em 5000.0vez de 5000.

Dinah
fonte
47

Supondo que você esteja usando o WinForms, Form.Opacityé do tipo double, portanto, você deve usar:

double trans = trackBar1.Value / 5000.0;
this.Opacity = trans;

A menos que você precise do valor em outro lugar, é mais fácil escrever:

this.Opacity = trackBar1.Value / 5000.0;

A razão pela qual o controle não funciona quando você alterou seu código para simplesmente ser um duplo foi porque você tinha:

double trans = trackbar1.Value / 5000;

que interpretou 5000como um número inteiro e, como trackbar1.Valuetambém é um número inteiro, seu transvalor sempre foi zero. Tornando explicitamente o valor numérico de ponto flutuante, adicionando .0o compilador, agora é possível interpretá-lo como um duplo e executar o cálculo adequado.

ChrisF
fonte
41

A melhor solução é:

this.Opacity = decimal.ToDouble(trackBar1.Value/5000);
Danny Fox
fonte
41

Como Opacityé um valor duplo, eu usaria apenas um dobro desde o início e não o lançaria, mas certifique-se de usar um dobro ao dividir para não perder precisão

Opacity = trackBar1.Value / 5000.0;
Darryl
fonte
36
this.Opacity = trackBar1.Value / 5000d;
Kolappan N
fonte