Konvertieren Sie Dezimal in Double

671

Ich möchte a verwenden Track-Bar, um Formdie Deckkraft von a zu ändern .

Das ist mein Code:

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

Wenn ich die Anwendung erstelle, wird der folgende Fehler angezeigt:

Konvertieren kann nicht implizit Art decimalzudouble

Ich habe versucht, transund doubledann Controlfunktioniert das nicht. Dieser Code hat in einem früheren VB.NET-Projekt einwandfrei funktioniert.

Eier McLaren
quelle
11
Außerdem kann Decimal keinen so breiten Wert wie Double darstellen. Die Dezimalzahl kann nur bis zu +/- 7,9228162514264337593543950335E + 28 reichen. wohingegen ein Double bis zu +/- 1.79769313486232E + 308
TraumaPony
7
Jemand sollte dieses als Duplikat markieren.
Ivan
7
@Ivan: Dies ist die 4. Frage, die SO jemals gestellt wurde ...
Nikolas
1
@ Nikolas: In der Tat. Heute hier verfolgt.
Juni

Antworten:

446

Eine explizite Besetzung, um doubledies zu mögen, ist nicht erforderlich:

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

Es ist ausreichend, die Konstante als 5000.0(oder als 5000d) zu identifizieren :

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

Eine allgemeinere Antwort auf die generische Frage "Decimal vs Double?": Dezimal für monetäre Berechnungen, um die Genauigkeit zu erhalten, Double für wissenschaftliche Berechnungen, die nicht von kleinen Unterschieden betroffen sind. Da Double ein Typ ist, der in der CPU nativ ist (interne Darstellung wird in Basis 2 gespeichert ), sind mit Double durchgeführte Berechnungen besser als Decimal ( intern in Basis 10 dargestellt ).

huseyint
quelle
83

Ihr Code hat in VB.NET einwandfrei funktioniert, da er implizit alle Casts ausführt, während C # sowohl implizite als auch explizite Casts enthält.

In C # ist die Konvertierung von dezimal nach doppelt explizit, da Sie an Genauigkeit verlieren. Zum Beispiel kann 1.1 nicht genau als Doppel ausgedrückt werden, sondern als Dezimalzahl (siehe " Gleitkommazahlen - ungenauer als Sie denken " aus dem Grund dafür).

In VB wurde die Konvertierung vom Compiler für Sie hinzugefügt:

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

Dies (double)muss explizit in C # angegeben werden, kann aber vom VB-Compiler "verzeihender" impliziert werden.

Keith
quelle
80

Warum dividierst du durch 5000? Stellen Sie einfach die Minimal- und Maximalwerte der TrackBar zwischen 0 und 100 ein und teilen Sie den Wert durch 100 für den Deckkraftprozentsatz. Das folgende Beispiel mit mindestens 20 verhindert, dass das Formular vollständig unsichtbar wird:

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
quelle
5
Würde dies das Problem nicht einfach verschieben? Anstatt ein Problem mit 5000, hätte OP ein Problem mit 100?
JWW
62

Sie haben zwei Probleme. Erstens Opacityerfordert ein Doppel, kein Dezimalwert. Der Compiler teilt Ihnen mit, dass es zwar eine Konvertierung zwischen Dezimal und Doppel gibt, es sich jedoch um eine explizite Konvertierung handelt, die Sie angeben müssen, damit sie funktioniert. Der zweite ist, dass TrackBar.Valuees sich um einen ganzzahligen Wert handelt und das Teilen eines int durch ein int zu einem int führt, unabhängig davon, welcher Art von Variable Sie es zuweisen. In diesem Fall gibt es eine implizite Umwandlung von int in dezimal oder doppelt - da bei der Umwandlung kein Genauigkeitsverlust auftritt - der Compiler beschwert sich also nicht, aber der Wert, den Sie erhalten, ist vermutlich immer 0, datrackBar.Valueist immer kleiner als 5000. Die Lösung besteht darin, Ihren Code so zu ändern, dass double (der native Typ für Deckkraft) und Gleitkomma-Arithmetik verwendet wird, indem die Konstante explizit zu einem Double gemacht wird - was die Arithmetik fördert - oder trackBar.Valuezu Double umgewandelt wird , die das Gleiche tun - oder beides. Oh, und Sie brauchen die Zwischenvariable nur, wenn sie anderweitig verwendet wird. Ich vermute, der Compiler würde es sowieso weg optimieren.

trackBar.Opacity = (double)trackBar.Value / 5000.0;
Tvanfosson
quelle
58

Meiner Meinung nach ist es wünschenswert, so explizit wie möglich zu sein. Dies erhöht die Klarheit des Codes und hilft Ihren Programmierkollegen, die ihn möglicherweise lesen.

Zusätzlich zum (oder anstelle von) Anhängen von a .0an die Nummer können Sie verwenden decimal.ToDouble().

Hier sind einige Beispiele:

// 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
quelle
57

Es hört sich so an, als wäre this.Opacityes ein doppelter Wert, und der Compiler mag es nicht, wenn Sie versuchen, einen Dezimalwert hinein zu stopfen.

Ryan Fox
quelle
50

Die Opacity- Eigenschaft ist vom doppelten Typ:

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

oder einfach:

this.Opacity = trackBar1.Value / 5000.0;

oder:

this.Opacity = trackBar1.Value / 5000d;

Beachten Sie, dass ich 5000.0(oder 5000d) verwende, um eine doppelte Division zu erzwingen, da trackBar1.Valuees sich um eine Ganzzahl handelt und eine Ganzzahldivision durchgeführt wird und das Ergebnis eine Ganzzahl ist.

Darin Dimitrov
quelle
49

Sie sollten 5000.0anstelle von verwenden 5000.

Dinah
quelle
47

Angenommen, Sie verwenden WinForms, Form.Opacityist vom Typ double, daher sollten Sie Folgendes verwenden:

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

Sofern Sie den Wert nicht an anderer Stelle benötigen, ist es einfacher zu schreiben:

this.Opacity = trackBar1.Value / 5000.0;

Der Grund, warum das Steuerelement nicht funktioniert, wenn Sie Ihren Code so geändert haben, dass er einfach doppelt ist, war, dass Sie:

double trans = trackbar1.Value / 5000;

was das 5000als eine ganze Zahl interpretierte , und weil trackbar1.Valuees auch eine ganze Zahl ist, war Ihr transWert immer Null. Indem .0der Compiler die Zahl explizit zu einem Gleitkommawert macht, indem er den numerischen Wert hinzufügt, kann er sie jetzt als Doppel interpretieren und die richtige Berechnung durchführen.

ChrisF
quelle
41

Die beste Lösung ist:

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

Da Opacityes sich um einen Doppelwert handelt, würde ich von Anfang an nur ein Doppel verwenden und überhaupt nicht wirken. Achten Sie jedoch darauf, beim Teilen ein Doppel zu verwenden, damit Sie keine Präzision verlieren

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