C# - 使用双精度的简单操作

本文关键字:简单 操作 双精度 | 更新日期: 2023-09-27 17:56:02

我写这个简单的程序只是为了显示我使用double操作时遇到的一个小问题。

namespace WpfApplication3
{
   public partial class MainWindow : Window
   {
        public MainWindow()
        {
            InitializeComponent();
            double a = 110.0;
            double b = a / 100.0;
            double c = Math.Round(b, 2);
            if ((c % 0.05) == 0)
                Console.WriteLine("Good news!");
            else
                Console.WriteLine("Bad news!");
        }
   }
}

做错了什么,如果运行该程序,在控制台上我看到"坏消息!....感谢您的意见,问候

C# - 使用双精度的简单操作

Double 不准确,您无法使用 float/double 精确表示所有数字,这会导致意外行为。所以你需要使用十进制:

decimal a = 110.0m;
decimal b = a / 100.0m;
decimal c = Math.Round(b, 2);
if ((c % 0.05m) == 0)
    Console.WriteLine("Good news!");
else
    Console.WriteLine("Bad news!");

输出:

Good news!

十进制类型的精度大于任何内置类型。 .NET 中的二进制浮点类型,尽管范围较小 的潜在指数。此外,许多操作产生了令人惊讶的结果 由于 原始操作数在十进制浮点数中消失,正是因为 许多操作数在源代码中专门表示为小数。 但是,这并不意味着所有操作突然变得 准确:例如,三分之一仍然不能完全代表。这 潜在问题与二进制浮动相同 点。但是,大多数情况下选择十进制类型 像钱一样的数量,操作会很简单,保持东西 准确。(例如,添加指定为 百分比将使数字保持准确,假设它们处于 从合理的范围开始。只要知道哪些操作是 可能会导致不准确,哪些不会导致不准确。

阅读本文了解更多信息。

学习使用断点并调试代码,以便学习如何解决自己的问题(在某些情况下)。让我们来看看您的应用程序。

    double a = 110.0;
    double b = a / 100.0;
    double c = Math.Round(b, 2); // c = 1.1
    if ((c % 0.05) == 0) // 1.1 % 0.05 = 0.000000000000000027755575615628914 which is not equal to 0.. thus it is false..
        Console.WriteLine("Good news!");
    else
        Console.WriteLine("Bad news!"); // Ooooh it's false, Bad news!

更新:

但是如果你改成..

    double a = 110.0;
    double b = a / 100.0;
    double c = Math.Round(b, 2); // c = 1.1
    if (Math.Round(c % 0.05) == 0) // 1.1 % 0.05 = 0.0 which is equal to 0.. thus it is true..
        Console.WriteLine("Good news!"); // Hurray!
    else
        Console.WriteLine("Bad news!");

此外,按照其他人的建议使用十进制数据类型将产生相同的结果。

使用

floatdouble 避免使用==!=比较,因为舍入错误,请改为与容差进行比较:

   ...
   double tolerance = 1e-6;
   // Comparison with tolerance: difference (if any) is less than tolerance
   if (Math.Abs(c % 0.05) < tolerance)
     Console.WriteLine("Good news!");
   else
     Console.WriteLine("Bad news!");