Преобразовать десятичную в двойную? - PullRequest
618 голосов
/ 01 августа 2008

Я хочу использовать трек-бар для изменения непрозрачности формы.

Это мой код:

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

При сборке приложения выдается следующая ошибка:

Невозможно неявно преобразовать тип 'decimal' в 'double'.

Я пытался использовать trans и double, но тогда управление не работает. Этот код прекрасно работал в прошлом проекте VB.NET.

Ответы [ 13 ]

420 голосов
/ 01 августа 2008

Явное приведение к удвоению, как это необязательно:

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

Достаточно указать постоянную как 5000.0 (или как 5000d):

double trans = trackBar1.Value / 5000.0;
double trans = trackBar1.Value / 5000d;
120 голосов
/ 01 августа 2008

Более общий ответ на общий вопрос «Десятичное число против двойного?»: Десятичное число для денежных расчетов, чтобы сохранить точность, Двойное для научных вычислений, на которые не влияют малые различия. Поскольку Double является типом, который является родным для ЦП (внутреннее представление хранится в base 2 ), вычисления, выполненные с Double, работают лучше, чем Decimal (который представлен внутри base 10 ) .

80 голосов
/ 10 августа 2008

Ваш код отлично работал в VB.NET, потому что он неявно выполняет любые приведения, в то время как в C # есть как неявные, так и явные.

В C # преобразование из десятичного в двойное явное, поскольку вы теряете точность. Например, 1.1 не может быть точно выражен как двойное число, но может быть как десятичное число (см. « Числа с плавающей запятой - более неточно, чем вы думаете » по причине).

В VB преобразование было добавлено для вас компилятором:

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

То, что (double) должно быть явно указано в C #, но может быть подразумеваемым более «прощающим» компилятором VB.

77 голосов
/ 21 сентября 2008

Почему вы делите на 5000? Просто установите минимальное и максимальное значения TrackBar в диапазоне от 0 до 100, а затем разделите значение на 100 для процента непрозрачности. Минимум 20 приведенных ниже примеров препятствуют тому, чтобы форма стала полностью невидимой:

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;
}
60 голосов
/ 27 февраля 2009

У вас две проблемы. Во-первых, Opacity требует двойного, а не десятичного значения. Компилятор говорит вам, что, хотя есть преобразование между десятичным и двойным, это явное преобразование, которое вам нужно указать, чтобы оно работало. Вторым является то, что TrackBar.Value является целочисленным значением, и деление int на int приводит к int независимо от того, к какому типу переменной вы его назначаете. В этом случае происходит неявное приведение от int к десятичному или двойному - потому что при выполнении преобразования нет потери точности - поэтому компилятор не будет жаловаться, но полученное вами значение всегда равно 0, предположительно, поскольку trackBar.Value всегда меньше 5000. Решение состоит в том, чтобы изменить ваш код на использование double (собственный тип для Opacity) и выполнять арифметику с плавающей запятой, явно делая константу double, что будет иметь эффект продвижения арифметики - или приведения 1004 *, чтобы удвоить, что будет делать то же самое - или оба. О, и вам не нужна промежуточная переменная, если она не используется в другом месте. Я предполагаю, что компилятор все равно его оптимизирует.

trackBar.Opacity = (double)trackBar.Value / 5000.0;
57 голосов
/ 06 августа 2008

На мой взгляд, желательно быть максимально явным. Это добавляет ясности к коду и помогает вашим коллегам-программистам, которые в конечном итоге могут его прочитать.

Помимо (или вместо) добавления .0 к номеру, вы можете использовать decimal.ToDouble().

Вот несколько примеров:

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

// Example 2 - with inline temp
this.Opacity = decimal.ToDouble(trackBar1.Value/5000);
55 голосов
/ 01 августа 2008

Похоже, что this.Opacity - двойное значение, и компилятору не нравится, когда вы пытаетесь втиснуть в него десятичное значение.

47 голосов
/ 20 ноября 2008

Вы должны использовать 5000.0 вместо 5000.

45 голосов
/ 31 августа 2011

Если вы используете WinForms, Form.Opacity имеет тип double, поэтому вы должны использовать:

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

Если вам не нужно значение в другом месте, проще написать:

this.Opacity = trackBar1.Value / 5000.0;

Причина, по которой элемент управления не работает, когда вы изменили код на простой, был в том, что у вас было:

double trans = trackbar1.Value / 5000;

, который интерпретировал 5000 как целое число, и поскольку trackbar1.Value также является целым числом, ваше значение trans всегда было равно нулю. Явно делая числовое значение с плавающей запятой добавлением .0, компилятор теперь может интерпретировать его как двойное число и выполнить правильный расчет.

45 голосов
/ 31 августа 2011

Свойство Непрозрачность имеет тип double:

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

или просто:

this.Opacity = trackBar1.Value / 5000.0;

или

this.Opacity = trackBar1.Value / 5000d;

Обратите внимание, что я использую 5000.0 (или 5000d) для принудительного двойного деления, потому что trackBar1.Value является целым числом, и оно будет выполнять целочисленное деление, а результатом будет целое число.

...