Konwertuj Dziesiętnie na Podwój

672

Chcę użyć a, Track-Baraby zmienić Formkrycie a.

To jest mój kod:

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

Podczas kompilowania aplikacji pojawia się następujący błąd:

Nie można niejawnie przekonwertować typu decimalnadouble

Próbowałem, używając transi doubleale wtedy Controlnie działa. Ten kod działał dobrze w poprzednim projekcie VB.NET.

Eggs McLaren
źródło
11
Ponadto liczba dziesiętna nie może reprezentować tak szerokiej wartości jak liczba podwójna. Liczba dziesiętna może wzrosnąć tylko do +/- 7,9228162514264337593543950335E + 28; mając na uwadze, że Double może wzrosnąć do +/- 1.79769313486232E + 308
TraumaPony
8
Ktoś powinien oznaczyć ten jako duplikat.
Ivan
8
@Ivan: To czwarte pytanie zadane SO w historii ...
Nikolas
1
@Nikolas: Rzeczywiście. Śledziłem tutaj dzisiaj.
czerwiec

Odpowiedzi:

447

Wyraźna obsada doubletego typu nie jest konieczna:

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

Identyfikacja stałej jako 5000.0(lub jako 5000d) jest wystarczająca:

double trans = trackBar1.Value / 5000.0;
double trans = trackBar1.Value / 5000d;
Kevin Dente
źródło
123

Bardziej ogólna odpowiedź na ogólne pytanie „Dziesiętne vs podwójne?”: Dziesiętne dla obliczeń pieniężnych w celu zachowania precyzji, Podwójne dla obliczeń naukowych, na które nie wpływają niewielkie różnice. Ponieważ Double jest typem rodzimym dla procesora (wewnętrzna reprezentacja jest przechowywana w bazie 2 ), obliczenia wykonane w Double działają lepiej niż dziesiętne (które są wewnętrznie reprezentowane w bazie 10 ).

huseyint
źródło
83

Twój kod działał dobrze w VB.NET, ponieważ domyślnie wykonuje wszelkie rzutowania, podczas gdy C # ma zarówno ukryte, jak i jawne.

W języku C # konwersja z dziesiętnej na podwójną jest wyraźna, gdy tracisz dokładność. Na przykład 1.1 nie może być dokładnie wyrażony jako liczba podwójna, ale może być ułamkiem dziesiętnym (zobacz „ Liczby zmiennoprzecinkowe - bardziej niedokładne niż myślisz ” z tego powodu).

W VB konwersja została dodana przez kompilator:

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

Że (double)musi być wyraźnie wskazane w C #, ale może być dorozumiany przez VB bardziej „wyrozumiały” kompilator.

Keith
źródło
80

Dlaczego dzielisz przez 5000? Wystarczy ustawić minimalną i maksymalną wartość TrackBar między 0 a 100, a następnie podzielić wartość przez 100 dla procentu Krycia. Minimalny przykład 20 poniżej zapobiega całkowicie niewidoczności formularza:

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
źródło
5
Czy to nie poruszyłoby problemu? Zamiast problemu z 5000OP miałby problem 100?
jww
62

Masz dwa problemy. Po pierwsze, Opacitywymaga podwójnej, a nie dziesiętnej wartości. Kompilator informuje, że chociaż istnieje konwersja między dziesiętną a podwójną, jest to wyraźna konwersja, którą należy określić, aby działała. Po drugie, TrackBar.Valuejest to liczba całkowita, a podzielenie liczby całkowitej przez liczbę całkowitą daje liczbę całkowitą bez względu na typ zmiennej, do której ją przypisujesz. W tym przypadku występuje niejawne rzutowanie z int na dziesiętne lub podwójne - ponieważ nie ma utraty precyzji podczas wykonywania rzutowania - więc kompilator nie narzeka, ale otrzymywana wartość wynosi zawsze 0, prawdopodobnie, ponieważtrackBar.Valuejest zawsze mniejsza niż 5000. Rozwiązaniem jest zmiana kodu, aby używał double (rodzimy typ dla Opacity) i wykonywał arytmetykę zmiennoprzecinkową, jawnie czyniąc stałą double - co spowoduje promowanie arytmetyki - lub rzut trackBar.Valuena double , który zrobi to samo - lub jedno i drugie. Aha, i nie potrzebujesz zmiennej pośredniej, chyba że jest używana gdzie indziej. Domyślam się, że kompilator i tak by go zoptymalizował.

trackBar.Opacity = (double)trackBar.Value / 5000.0;
tvanfosson
źródło
58

Moim zdaniem pożądane jest, aby być jak najbardziej wyraźnym. To dodaje przejrzystości kodu i pomaga innym programistom, którzy mogą go w końcu przeczytać.

Oprócz (lub zamiast) dodawania a .0do numeru możesz użyć decimal.ToDouble().

Oto kilka przykładów:

// 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
źródło
57

Wygląda na this.Opacityto, że jest to podwójna wartość, a kompilator nie lubi próbować wcisnąć w nią wartości dziesiętne.

Ryan Fox
źródło
50

Właściwość Opacity jest podwójnego typu:

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

lub po prostu:

this.Opacity = trackBar1.Value / 5000.0;

lub:

this.Opacity = trackBar1.Value / 5000d;

Zauważ, że używam 5000.0(lub 5000d) do wymuszenia podwójnego podziału, ponieważ trackBar1.Valuejest liczbą całkowitą i wykonałby podział liczby całkowitej, a wynikiem byłaby liczba całkowita.

Darin Dimitrov
źródło
49

Powinieneś użyć 5000.0zamiast 5000.

Dina
źródło
47

Zakładając, że używasz WinForms, Form.Opacityjest typu double, więc powinieneś użyć:

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

O ile nie potrzebujesz wartości w innym miejscu, łatwiej jest napisać:

this.Opacity = trackBar1.Value / 5000.0;

Powodem, dla którego formant nie działa, gdy zmienisz kod na zwykły podwójny, było to, że:

double trans = trackbar1.Value / 5000;

który interpretował 5000jako liczbę całkowitą, a ponieważ trackbar1.Valuejest także liczbą całkowitą, twoja transwartość zawsze wynosiła zero. Poprzez jawne uczynienie z liczby zmiennoprzecinkowej przez dodanie .0kompilatora można teraz zinterpretować ją jako podwójną i wykonać właściwe obliczenia.

ChrisF
źródło
41

Najlepszym rozwiązaniem jest:

this.Opacity = decimal.ToDouble(trackBar1.Value/5000);
Danny Fox
źródło
41

Ponieważ Opacityjest to podwójna wartość, po prostu użyłbym podwójnej od samego początku i wcale nie rzucałem, ale pamiętaj, aby użyć podwójnej przy dzieleniu, abyś nie stracił żadnej precyzji

Opacity = trackBar1.Value / 5000.0;
Darryl
źródło
36
this.Opacity = trackBar1.Value / 5000d;
Kolappan N.
źródło
0

Spróbuj tego:

Opacity = decimal.ToDouble(trackBar1.Value / 5000.0);```
TheZBLL
źródło