Как преобразовать десятичную дробь в двойную в C#?

Я хочу использовать Track-Bar для изменения Form непрозрачности.

Это мой код:

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

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

Cannot implicitly convert type decimal to double

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

Ответов (14)

Решение

Явное приведение к double этому не требуется:

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

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

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

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

Лучшее решение:

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

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

Opacity = trackBar1.Value / 5000.0;
this.Opacity = trackBar1.Value / 5000d;

Попробуйте использовать функцию приведения:

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

Более общий ответ на общий вопрос «Десятичное или двойное?»:

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

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

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

В дополнение к (или вместо) добавления .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);

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

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

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

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

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

Почему вы делите на 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;
}

У вас две проблемы.

Во-первых, Opacity требуется двойное, а не десятичное значение. Компилятор сообщает вам, что, хотя существует преобразование между десятичным и двойным числом, это явное преобразование, которое вам необходимо указать, чтобы оно работало.

Во-вторых, TrackBar.Value это целочисленное значение, и деление int на int приводит к int независимо от того, какой тип переменной вы его назначаете. В этом случае происходит неявное приведение типа int к decimal или double, потому что при приведении нет потери точности. Так что компилятор не жалуется. Но значение, которое вы получаете, по-видимому, trackBar.Value всегда равно 0, поскольку оно всегда меньше 5000.

Решение состоит в том, чтобы изменить ваш код, чтобы использовать double (собственный тип для Opacity) и выполнять арифметику с плавающей запятой, явно сделав константу double, что приведет к повышению арифметики или приведению trackBar.Value к двойному, что будет делать то же самое. или оба. Вам не нужна промежуточная переменная, если она не используется где-либо еще. Я предполагаю, что компилятор все равно оптимизирует его.

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

Предполагая, что вы используете 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 компилятор теперь может интерпретировать его как двойное и выполнить правильное вычисление.

Свойство Opacity имеет двойной тип:

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это целое число, и он будет выполнять целочисленное деление, и результат будет целым числом.