将不透明度应用于表单时,我们应该使用小数还是双精度值?


543

我想使用轨迹栏来更改窗体的不透明度。

这是我的代码:

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

当我构建应用程序,它提供了以下错误:

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

我尝试使用transdouble但随后的控制不起作用。此代码在过去的VB.NET项目中运行良好。

+8

此外,十进制不能代表同样宽的值作为双人。十进制只能达到+/- 7.9228162514264337593543950335E + 28;而一个Double可以达到+/- 1.79769313486232E + 308 21 9月. 082008-09-21 04:09:42

391

显式转换到加倍像这不是必需的:

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

识别常数5000.0(或作为5000d)足以:

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

53

这听起来像this.Opacity是双值,并且编译器不喜欢你尝试将十进制值塞进它中。


112

一个更通用的答案一般问题“十进制VS双?”:十进制货币计算,以保持精度,对于没有得到受微小差异的科学计算。由于Double是CPU原生类型(内部表示存储在的基数2中),因此使用Double执行的计算性能会更好,然后执行Decimal(内部表示为基数10)。


55

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

除了(或代替)将.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); 

74

您的代码在VB.NET工作得很好,因为它确实隐含任何类型转换,而C#既有隐和外显的。

在C#中,从十进制到双精度的转换是明确的,因为您失去了准确性。例如1.1不能准确地表示为双精度,但可以作为小数(因为原因,请参阅“Floating point numbers - more inaccurate than you think”)。

在VB是由编译器为你添加的转换:

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

(double)必须在C#中明确阐述,但可以通过VB的更多的“宽容”编译器暗示


73

你为什么除以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; 
} 
+3

这难道不会只是解决问题吗?与'5000'不一样的问题,OP会对'100'有问题? 22 9月. 142014-09-22 21:17:56


45

您应该使用5000.0而不是5000


56

你有两个问题。首先,Opacity需要双精度值,而不是十进制值。编译器告诉你,虽然在十进制和双精度之间有一个转换,但它是一个显式转换,你需要指定它以使其工作。第二个是TrackBar.Value是一个整数值,并且将一个int除以int得到的结果是一个int,而不管分配给它的是哪种类型的变量。在这种情况下,存在从int到decimal或double的隐式转换 - 因为在执行转换时没有精度损失 - 所以编译器不会发出抱怨,但是您得到的值始终为0,可能是因为trackBar.Value是总是小于5000.解决方案是将您的代码更改为使用double(Opacity的本机类型),并通过明确地将该常量设置为double来执行浮点运算 - 这将具有促进算术运算的效果 - 或者将trackBar.Value的值加倍,这将做同样的事情 - 或两者兼而有之。哦,你不需要中间变量,除非在其他地方使用。无论如何,我的猜测是编译器会优化它。

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

44

Opacity属性是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是一个整数,它将执行整数除法并且结果将是整数。


42

假设你正在使用的WinForms,Form.Opacitydouble类型的,所以你应该使用:

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

除非你需要在其他地方的价值,这是简单的写:

this.Opacity = trackBar1.Value/5000.0; 

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

double trans = trackbar1.Value/5000; 

5000解释为整数,因此您的trans值始终为零。通过添加.0明确地将数字设置为浮点值,编译器现在可以将其解释为double并执行正确的计算。


38

最好的解决办法是:

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

37

由于Opacity是一个双重价值,我只想用一个双从一开始就与不投所有,但可以肯定的划分,所以你不要当使用双“T丢失任何精度

Opacity = trackBar1.Value/5000.0; 

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