关于C#: Decimal转 Double

关于C#: Decimal转 Double

Convert Decimal to Double?

我想使用跟踪栏更改窗体的不透明度。

这是我的代码:

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

当我构建应用程序时,它会给出以下错误:

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

我试过使用transdouble,但是控制不起作用。这段代码在过去的vb.net项目中运行良好。


不需要像这样显式转换为double:

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

将常数标识为5000.0(或5000d)就足够了:

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

对一般性问题"十进制与双精度"的更一般的回答。:小数表示货币计算以保持精度,两倍表示不受小差异影响的科学计算。由于double是CPU本身的一种类型(内部表示法存储在基2中),因此使用double进行的计算比使用decimal(内部表示法为基10)执行得更好。


您的代码在vb.net中工作得很好,因为它隐式地执行任何类型转换,而C同时具有隐式和显式两种类型。

在C中,从十进制到double的转换是明确的,因为您会失去准确性。例如,1.1不能准确地表示为双精度数,但可以表示为十进制数(请参阅"浮点数-比您想象的更不准确"了解原因)。

在VB中,编译器为您添加了转换:

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

(double)必须在c中明确说明,但可以通过vb更"宽容"的编译器来暗示。


你为什么除以5000?只需将轨迹条的最小值和最大值设置为0到100,然后将不透明度百分比的值除以100。以下至少20个示例可防止窗体完全不可见:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
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需要一个双精度值,而不是十进制值。编译器告诉您,尽管十进制和double之间存在转换,但它是一个显式转换,您需要指定它才能工作。第二个问题是,TrackBar.Value是一个整数值,将一个int除以一个int,结果就是一个int,无论您将它赋给什么类型的变量。在这种情况下,有一个从int到decimal或double的隐式强制转换-因为在执行强制转换时不会丢失精度-所以编译器不会抱怨,但是您得到的值总是0,大概是因为TrackBar.Value总是小于5000。解决方案是将代码更改为使用double(不透明度的本机类型),并通过显式地将常量设为double来执行浮点运算,这将具有提升算法的效果,或者将TrackBar.Value强制转换为double,这将执行相同的操作,或者两者兼而有之。除非在别处使用,否则不需要中间变量。我猜编译器会把它优化掉。

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

在我看来,最好尽可能明确。这增加了代码的清晰度,并帮助您的程序员同事最终阅读它。

除了(或代替)在数字上附加一个.0,您还可以使用decimal.ToDouble()

以下是一些例子:

1
2
3
4
5
6
// Example 1
double transperancy = trackBar1.Value/5000;
this.Opacity = decimal.ToDouble(transperancy);

// Example 2 - with inline temp
this.Opacity = decimal.ToDouble(trackBar1.Value/5000);


听起来this.Opacity是一个双精度值,编译器不希望您试图在其中填充十进制值。


你应该使用5000.0而不是5000


假设您使用的是WinForms,那么Form.Opacity的类型是double的类型,因此您应该使用:

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

除非您在其他地方需要该值,否则编写:

1
this.Opacity = trackBar1.Value / 5000.0;

当您将代码更改为简单的double时,控件不起作用的原因是:

1
double trans = trackbar1.Value / 5000;

它将5000解释为整数,因为trackBar1.Value也是整数,所以trans的值始终为零。通过添加.0,显式地将数字变为浮点值,编译器现在可以将其解释为双精度数并执行正确的计算。


不透明度属性为双类型:

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

或者简单地说:

1
this.Opacity = trackBar1.Value / 5000.0;

或:

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

注意,我使用5000.05000d强制进行双除法,因为trackBar1.Value是一个整数,它将执行整数除法,结果将是一个整数。


因为Opacity是一个双精度值,所以我从一开始就使用双精度值,根本不用强制转换,但是在进行除法时一定要使用双精度值,这样就不会丢失任何精度。

1
Opacity = trackBar1.Value / 5000.0;


最好的解决方案是:

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

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


推荐阅读