Convertir décimal en double

672

Je veux utiliser a Track-Barpour changer Forml'opacité de a.

Voici mon code:

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

Lorsque je crée l'application, cela donne l'erreur suivante:

Impossible de convertir implicitement le type decimalendouble

J'ai essayé d'utiliser transet doublepuis Controlça ne marche pas. Ce code a bien fonctionné dans un ancien projet VB.NET.

Oeufs McLaren
la source
11
En outre, Decimal ne peut pas représenter une valeur aussi large qu'un Double. La décimale ne peut aller que jusqu'à +/- 7,9228162514264337593543950335E + 28; alors qu'un Double peut aller jusqu'à +/- 1.79769313486232E + 308
TraumaPony
8
Quelqu'un devrait marquer celui-ci comme doublon.
Ivan
8
@Ivan: C'est la 4ème question posée sur SO ever ...
Nikolas
1
@Nikolas: En effet. Tracé ici aujourd'hui.
juin

Réponses:

447

Un cast explicite pour doubleaimer cela n'est pas nécessaire:

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

Identifier la constante comme 5000.0(ou comme 5000d) suffit:

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

Une réponse plus générique à la question générique "Décimal vs Double?": Décimal pour les calculs monétaires afin de préserver la précision, Double pour les calculs scientifiques qui ne sont pas affectés par de petites différences. Étant donné que Double est un type natif du CPU (la représentation interne est stockée dans la base 2 ), les calculs effectués avec Double fonctionnent mieux que Decimal (qui est représenté en base 10 en interne).

huseyint
la source
83

Votre code a bien fonctionné dans VB.NET car il effectue implicitement toutes les conversions, tandis que C # en a à la fois implicites et explicites.

En C #, la conversion de décimal en double est explicite car vous perdez en précision. Par exemple, 1.1 ne peut pas être exprimé avec précision sous la forme d'un double, mais peut être décimal (voir « Numéros à virgule flottante - plus imprécis que vous ne le pensez » pour la raison).

Dans VB, la conversion a été ajoutée pour vous par le compilateur:

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

Cela (double)doit être explicitement indiqué en C #, mais peut être implicite par le compilateur plus «indulgent» de VB.

Keith
la source
80

Pourquoi divisez-vous par 5000? Définissez simplement les valeurs minimum et maximum du TrackBar entre 0 et 100, puis divisez la valeur par 100 pour le pourcentage d'opacité. L'exemple minimum 20 ci-dessous empêche le formulaire de devenir complètement invisible:

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
la source
5
Cela ne déplacerait-il pas simplement le problème? Plutôt qu'un problème avec 5000, OP aurait un problème avec 100?
JWW
62

Vous avez deux problèmes. Tout d'abord, Opacitynécessite une valeur double et non décimale. Le compilateur vous dit que bien qu'il y ait une conversion entre décimal et double, c'est une conversion explicite que vous devez spécifier pour que cela fonctionne. La seconde est qu'il TrackBar.Values'agit d'une valeur entière et la division d'un int par un int entraîne un int quel que soit le type de variable auquel vous l'assignez. Dans ce cas, il y a une conversion implicite de int en décimal ou double - car il n'y a aucune perte de précision lorsque vous effectuez la conversion - donc le compilateur ne se plaint pas, mais la valeur que vous obtenez est toujours 0, probablement, cartrackBar.Valueest toujours inférieur à 5000. La solution est de changer votre code pour utiliser le double (le type natif pour l'opacité) et faire de l'arithmétique à virgule flottante en faisant explicitement de la constante un double - ce qui aura pour effet de promouvoir l'arithmétique - ou de transtyper trackBar.Valueen double , qui fera la même chose - ou les deux. Oh, et vous n'avez pas besoin de la variable intermédiaire à moins qu'elle ne soit utilisée ailleurs. Je suppose que le compilateur l'optimiserait de toute façon.

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

À mon avis, il est souhaitable d'être aussi explicite que possible. Cela ajoute de la clarté au code et aide vos collègues programmeurs qui pourraient éventuellement le lire.

En plus (ou au lieu de) d'ajouter un .0au numéro, vous pouvez utiliser decimal.ToDouble().

Voici quelques exemples:

// 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
la source
57

Cela ressemble à this.Opacityune double valeur, et le compilateur n'aime pas que vous essayiez d'y insérer une valeur décimale.

Ryan Fox
la source
50

La propriété Opacity est de type double:

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

ou simplement:

this.Opacity = trackBar1.Value / 5000.0;

ou:

this.Opacity = trackBar1.Value / 5000d;

Notez que j'utilise 5000.0(ou 5000d) pour forcer une double division car trackBar1.Valueest un entier et il effectuerait une division entière et le résultat serait un entier.

Darin Dimitrov
la source
49

Vous devez utiliser à la 5000.0place de 5000.

Dinah
la source
47

En supposant que vous utilisez WinForms, Form.Opacityest de type double, vous devez donc utiliser:

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

Sauf si vous avez besoin de la valeur ailleurs, il est plus simple d'écrire:

this.Opacity = trackBar1.Value / 5000.0;

La raison pour laquelle le contrôle ne fonctionne pas lorsque vous avez modifié votre code pour qu'il soit simplement un double est dû au fait que vous aviez:

double trans = trackbar1.Value / 5000;

qui a interprété le 5000comme un entier, et parce que trackbar1.Valuec'est aussi un entier, votre transvaleur était toujours nulle. En faisant explicitement du numérique une valeur à virgule flottante en ajoutant le .0compilateur, il peut désormais l'interpréter comme un double et effectuer le calcul approprié.

ChrisF
la source
41

La meilleure solution est:

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

Puisqu'il Opacitys'agit d'une valeur double, j'utiliserais simplement un double dès le départ et pas du tout, mais assurez-vous d'utiliser un double lors de la division afin de ne perdre aucune précision

Opacity = trackBar1.Value / 5000.0;
Darryl
la source
36
this.Opacity = trackBar1.Value / 5000d;
Kolappan N
la source
0

Essaye ça:

Opacity = decimal.ToDouble(trackBar1.Value / 5000.0);```
user12828597
la source