2008-07-31 15 views
543

Chcę użyć paska śledzenia, aby zmienić nieprzezroczystość formularza.Stosując krycie do formularza, należy użyć wartości dziesiętnej lub podwójnej?

To jest mój kod:

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

Kiedy zbudować aplikację, daje następujący błąd:

Cannot implicitly convert type 'decimal' to 'double' .

Próbowałem za pomocą trans i double ale wtedy sterowania nie działa. Kod ten działał dobrze w poprzednim projekcie VB.NET.

+8

również dziesiętny nie może reprezentować tak szeroka wartość jako podwójne. Dziesiętny może wzrosnąć tylko do +/- 7,9228162514264337593543950335E + 28; mając na uwadze, że Double może wzrosnąć do +/- 1,79769313486232E + 308 – TraumaPony

Odpowiedz

391

Wyraźne obsada podwoić jak nie jest to konieczne:

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

identyfikujący stałą jako 5000.0 (lub jak 5000d) jest wystarczająca:

double trans = trackBar1.Value/5000.0; 
double trans = trackBar1.Value/5000d; 
53

Brzmi jak this.Opacity jest podwójnie wartość, a kompilator nie lubi, aby próbować wtłoczyć do niego wartość dziesiętną.

112

Bardziej ogólne odpowiedź na pytanie rodzajowe „dziesiętny vs dwuosobowe?”: dziesiętny dla obliczenia pieniężne, aby zachować precyzję, podwójne do obliczeń naukowych, które nie uzyskać dotkniętych małych różnic. Ponieważ Double jest rodzajem natywnym dla procesora (wewnętrzna reprezentacja jest przechowywana w base 2), obliczenia wykonane za pomocą Double działają lepiej niż dziesiętny (który jest reprezentowany wewnętrznie w postaci base 10).

55

Moim zdaniem pożądane jest, aby było tak wyraźne, jak to tylko możliwe. To dodaje klarowności do kodu i pomaga innym programistom, którzy mogą go w końcu przeczytać.

Oprócz (lub zamiast) dołączania do numeru .0 można użyć numeru 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); 
74

Twój kod pracował dobrze w VB.NET, ponieważ domyślnie ma żadnych rzutów, podczas gdy C# ma obie te niejawne i jawne.

W języku C# konwersja z dziesiętnej na podwójną jest wyraźna, ponieważ traci się celność. Na przykład 1.1 nie może być dokładnie wyrażone jako podwójne, ale może być dziesiętne (patrz "Floating point numbers - more inaccurate than you think" z tego powodu).

W VB konwersja została dodana do ciebie przez kompilator:

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

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

73

Dlaczego dzielisz przez 5000? Wystarczy ustawić minimalne i maksymalne wartości TrackBar między 0 a 100, a następnie podzielić wartość przez 100 dla procentu krycia.Minimalna 20 Przykład poniżej zapobiega formularza z coraz całkowicie niewidoczny:

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; 
} 
+3

Czy to nie wystarczyłoby, aby poruszyć problem? Zamiast problemu z '5000', OP miałby problem z' 100'? – jww

45

Należy użyć 5000.0 zamiast 5000.

56

Masz dwa problemy. Po pierwsze, Opacity wymaga podwójnej, a nie dziesiętnej wartości. Kompilator mówi ci, że chociaż istnieje konwersja między dziesiętną i podwójną, jest to wyraźna konwersja, którą musisz określić, aby działała. Druga to to, że TrackBar.Value jest wartością całkowitą, a dzielenie int przez int daje w wyniku wartość int bez względu na typ zmiennej, do której ją przypiszesz. W tym przypadku istnieje niejawne rzutowanie z int na dziesiętne lub podwójne - ponieważ nie ma utraty dokładności podczas wykonywania rzutowania - więc kompilator nie narzeka, ale wartość, którą otrzymujesz, zawsze wynosi 0, prawdopodobnie, ponieważ trackBar.Value jest zawsze mniej niż 5000. Rozwiązaniem jest zmiana twojego kodu na podwójny (natywny typ dla Opacity) i arytmetyka zmiennoprzecinkowa poprzez jawne zrobienie stałej podwójnej - która spowoduje efekt arytmetyczny - lub rzucenie trackBar.Value w celu podwojenia , który zrobi to samo - lub oba. Aha, i nie potrzebujesz zmiennej pośredniej, chyba że jest używana gdzie indziej. Domyślam się, że kompilator i tak go zoptymalizuje.

trackBar.Opacity = (double)trackBar.Value/5000.0; 
44

Obiekt Opacity jest typu double:

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

lub po prostu:

this.Opacity = trackBar1.Value/5000.0; 

czyli

this.Opacity = trackBar1.Value/5000d; 

Zauważ, że używam 5000.0 (lub 5000d) w celu wymuszenia podwójnego podziału, ponieważ trackBar1.Value jest liczbą całkowitą i wykona podział całkowity, a wynikiem będzie liczba całkowita.

42

Zakładając, że używasz WinForms, Form.Opacity jest typu double, więc należy używać:

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

ile trzeba wartość gdzie indziej, to prościej napisać:

this.Opacity = trackBar1.Value/5000.0; 

powodem Kontrola nie działa, gdy zmieniłeś kod, aby po prostu być podwójnym, ponieważ masz:

double trans = trackbar1.Value/5000; 

który interpretował 5000 jako liczbę całkowitą, więc twoja wartość trans była zawsze równa zero. Poprzez jawne nadanie wartości numerycznej wartości zmiennoprzecinkowej poprzez dodanie .0, kompilator może teraz interpretować ją jako podwójną i wykonać odpowiednie obliczenia.

38

Najlepszym rozwiązaniem jest:

this.Opacity = decimal.ToDouble(trackBar1.Value/5000); 
37

Od Opacity to podwójna wartość, chciałbym po prostu użyć podwójnego od samego początku i nie rzucać w ogóle, ale należy użyć podwójnego przy podziale więc don „t tracą zupełnie precyzja

Opacity = trackBar1.Value/5000.0; 
31
this.Opacity = trackBar1.Value/5000d; 
Powiązane problemy