【问题标题】:How to convert a Decimal to a Double in C#?如何在 C# 中将 Decimal 转换为 Double?
【发布时间】:2010-09-05 05:27:08
【问题描述】:

我想使用Track-Bar 来更改Form 的不透明度。

这是我的代码:

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

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

Cannot implicitly convert type decimal to double

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

【问题讨论】:

  • 另外,Decimal 不能表示像 Double 一样宽的值。十进制最多只能达到 +/-7.9228162514264337593543950335E+28;而 Double 可以达到 +/-1.79769313486232E+308
  • @TraumaPony 这是一个trackbar。在trackbar上使用如此高的价值是不可能的。
  • 总是有人告诉我,乘以 0.0002 比除以 5000 更好。

标签: c# floating-point type-conversion double decimal


【解决方案1】:

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

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

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

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

【讨论】:

    【解决方案2】:

    对于通用问题“十进制与双精度?”的更通用答案:

    十进制用于货币计算以保持精度。 Double 用于不受微小差异影响的科学计算。由于 Double 是 CPU 原生的类型(内部表示存储在 base 2 中),使用 Double 进行的计算比 Decimal 执行得更好(以 base 10 表示内部)。

    【讨论】:

      【解决方案3】:

      您的代码在 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 更“宽容”的编译器暗示

      【讨论】:

        【解决方案4】:

        为什么要除以 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;
        }
        

        【讨论】:

        • 这不会解决问题吗?而不是5000 的问题,OP 会遇到100 的问题?
        【解决方案5】:

        你有两个问题。

        首先,Opacity 需要一个双精度值,而不是十进制值。编译器告诉您,虽然小数和双精度之间存在转换,但您需要指定显式转换才能使其工作。

        其次,TrackBar.Value 是一个整数值,并且将一个 int 除以一个 int 会得到一个 int,无论您将它分配给什么类型的变量。在这种情况下,存在从 int 到 decimal 或 double 的隐式转换,因为在进行转换时不会损失精度。所以编译器不会抱怨。但是你得到的值总是0,大概是因为trackBar.Value总是小于5000。

        解决方案是将代码更改为使用双精度(不透明度的本机类型)并通过显式将常量设为双精度来执行浮点运算,这将具有提升算术或将trackBar.Value 转换为双精度的效果,这将做同样的事情或两者兼而有之。您不需要中间变量,除非它在其他地方使用。我的猜测是编译器无论如何都会优化它。

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

        【讨论】:

          【解决方案6】:

          在我看来,希望尽可能明确。这增加了代码的清晰度,并有助于最终可能阅读它的程序员伙伴。

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

          【讨论】:

            【解决方案7】:

            听起来this.Opacity 是一个双精度值,编译器不喜欢你尝试在其中塞入一个十进制值。

            【讨论】:

              【解决方案8】:

              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 是一个整数,它会执行整数除法,结果将是一个整数。

              【讨论】:

                【解决方案9】:

                您应该使用5000.0 而不是5000

                【讨论】:

                  【解决方案10】:

                  假设您使用的是 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 显式将数字设为浮点值,编译器现在可以将其解释为双精度并执行正确的计算。

                  【讨论】:

                    【解决方案11】:

                    由于Opacity 是一个双精度值,我会从一开始就使用双精度而不是强制转换,但一定要在除法时使用双精度,以免丢失任何精度

                    Opacity = trackBar1.Value / 5000.0;
                    

                    【讨论】:

                      【解决方案12】:

                      最好的解决办法是:

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

                      【讨论】:

                        猜你喜欢
                        • 2014-09-13
                        • 1970-01-01
                        • 1970-01-01
                        • 1970-01-01
                        • 2010-10-29
                        • 1970-01-01
                        • 2023-01-23
                        • 2011-12-10
                        • 2021-12-10
                        相关资源
                        最近更新 更多