扩展一个double的方法,实现两个值相减小于0.0001,算相等。

博客围绕公司出的一道C#扩展方法题目展开。因double类型精度不同,计算得到的double数据用常规方法判断相等会有问题。先给出错误解法,后强调本题重点是对扩展方法的理解,介绍创建扩展方法步骤并给出正确解法及调用示例。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

公司领导除了这样一个题,第一遍,我意思都没读懂,后来理解了,需要写一个扩展方法。这在C#中也是很重要的一个知识点。

至于为什么两个数为什么相减等于0不就可以了?

这是因为这两个数据是double类型,精度是不同的。

如果是两个已经复制的double变量,那么你可以通过a==b来判断两个数是否相等。

可如果你是通过计算得到的两个double数据,有可能即使相等,也会认为这两个double数据不相等,这就是这道题的由来!

我的解:

public static bool IsEquals(this double a,double b,double standard)
        {
            if (a - b > standard ||
                a - b < -standard)
            {
                Console.WriteLine("不相等");
                return false;
            }
            Console.WriteLine("相等");
            return true;
        }

 

在主函数里调用:

IsEquals(2.0001, 2.00001, 0.0001);

然而这并不是扩展方法!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!!

其实这题主要考的是,对扩张方法的理解:

创建扩展方法很简单,有以下几个步骤:
1、创建一个静态类;
2、在其中创建一个静态方法;
3、为这个静态方法添加至少一个参数,并在第一个参数前加上this关键字,这个关键字会告诉编译器当前方法是一个扩展方法。而这个方法将成为第一个参数所属类型的新成员。
所以正确的解法是:

public static class DoubleExtension
    {
        private const double Threshold = 0.00001;

        public static bool IsEquals(this double a, double b)
        {
            if (a - b > Threshold ||
                a - b < -Threshold)
            {
                Console.WriteLine("{0} != {1}", a, b);
                return false;
            }
            Console.WriteLine("{0}  = {1}", a, b);
            return true;
        }
    }

 

这样去调用:

             //测试double扩展方法
            Console.WriteLine("测试double扩展方法.....");
            double parameterOne = 2.0001, parameterTwo = 2.00001;
            parameterOne.IsEquals(parameterTwo);

 

 

 

Module 矩形排序模块 ' 定义多段线数据结构体 Private Structure PolylineData Public Polyline As AcadLWPolyline ' CAD多段线对象 Public CenterX As Double ' 中心点X坐标 Public CenterY As Double ' 中心点Y坐标 End Structure ' 判断是否在同一行(严格应用行容差) Private Function IsSameRow(y1 As Double, y2 As Double, rowTolerance As Double) As Boolean ' 比较Y坐标差是否在容差范围内 Return Math.Abs(y1 - y2) <= rowTolerance End Function ' 判断是否在同一列(严格应用列容差) Private Function IsSameCol(x1 As Double, x2 As Double, colTolerance As Double) As Boolean ' 比较X坐标差是否在容差范围内 Return Math.Abs(x1 - x2) <= colTolerance End Function ' 改进的分组函数(严格应用容差) Private Function GroupByTolerance(data As List(Of PolylineData), rowTolerance As Double, colTolerance As Double) As List(Of List(Of PolylineData)) ' 初始化分组列表 Dim groupedData As New List(Of List(Of PolylineData)) ' 对每个元素进行分组 For Each item In data Dim foundGroup = False ' 尝试将元素放入现有组 For Each group In groupedData ' 严格检查容差条件 If IsSameRow(group(0).CenterY, item.CenterY, rowTolerance) AndAlso IsSameCol(group(0).CenterX, item.CenterX, colTolerance) Then group.Add(item) foundGroup = True Exit For End If Next ' 未找到合适组则创建新组 If Not foundGroup Then groupedData.Add(New List(Of PolylineData) From {item}) End If Next Return groupedData End Function ' 完整排序函数(支持所有组合方向) Public Sub SortPolylines(polylines As List(Of AcadLWPolyline), rule As 排序规则, rowTolerance As Double, colTolerance As Double) ' 计所有多段线中心点 Dim polylineData = polylines.Select(Function(p) Dim bounds = GetPolylineBounds(p) Return New PolylineData With { .Polyline = p, .CenterX = (bounds.MaxX + bounds.MinX) / 2, .CenterY = (bounds.MaxY + bounds.MinY) / 2 } End Function).ToList() ' 使用容差进行分组 Dim groupedData = GroupByTolerance(polylineData, rowTolerance, colTolerance) ' 根据排序规则处理分组 Select Case rule ' 1. 先行后列组合 Case 排序规则.先行后列_X升序_Y升序 ' 左下→右上 groupedData.Sort(Function(g1, g2) g1(0).CenterY.CompareTo(g2(0).CenterY)) ' Y升序 For Each group In groupedData group.Sort(Function(a, b) a.CenterX.CompareTo(b.CenterX)) ' X升序 Next Case 排序规则.先行后列_X升序_Y降序 ' 左上→右下 groupedData.Sort(Function(g1, g2) g2(0).CenterY.CompareTo(g1(0).CenterY)) ' Y降序 For Each group In groupedData group.Sort(Function(a, b) a.CenterX.CompareTo(b.CenterX)) ' X升序 Next Case 排序规则.先行后列_X降序_Y升序 ' 右下→左上 groupedData.Sort(Function(g1, g2) g1(0).CenterY.CompareTo(g2(0).CenterY)) ' Y升序 For Each group In groupedData group.Sort(Function(a, b) b.CenterX.CompareTo(a.CenterX)) ' X降序 Next Case 排序规则.先行后列_X降序_Y降序 ' 右上→左下 groupedData.Sort(Function(g1, g2) g2(0).CenterY.CompareTo(g1(0).CenterY)) ' Y降序 For Each group In groupedData group.Sort(Function(a, b) b.CenterX.CompareTo(a.CenterX)) ' X降序 Next ' 2. 先列后行组合 Case 排序规则.先列后行_Y升序_X升序 ' 左下→右上 groupedData.Sort(Function(g1, g2) g1(0).CenterX.CompareTo(g2(0).CenterX)) ' X升序 For Each group In groupedData group.Sort(Function(a, b) a.CenterY.CompareTo(b.CenterY)) ' Y升序 Next Case 排序规则.先列后行_Y升序_X降序 ' 右下→左上 groupedData.Sort(Function(g1, g2) g2(0).CenterX.CompareTo(g1(0).CenterX)) ' X降序 For Each group In groupedData group.Sort(Function(a, b) a.CenterY.CompareTo(b.CenterY)) ' Y升序 Next Case 排序规则.先列后行_Y降序_X升序 ' 左上→右下 groupedData.Sort(Function(g1, g2) g1(0).CenterX.CompareTo(g2(0).CenterX)) ' X升序 For Each group In groupedData group.Sort(Function(a, b) b.CenterY.CompareTo(a.CenterY)) ' Y降序 Next Case 排序规则.先列后行_Y降序_X降序 ' 右上→左下 groupedData.Sort(Function(g1, g2) g2(0).CenterX.CompareTo(g1(0).CenterX)) ' X降序 For Each group In groupedData group.Sort(Function(a, b) b.CenterY.CompareTo(a.CenterY)) ' Y降序 Next Case 排序规则.绘图顺序 ' 保持原顺序 ' 不进行排序 End Select ' 合并排序结果 Dim sortedPolylines As New List(Of AcadLWPolyline) For Each group In groupedData For Each item In group sortedPolylines.Add(item.Polyline) Next Next ' 更新原始集合 polylines.Clear() polylines.AddRange(sortedPolylines) End Sub ' 获取多段线边界 Private Function GetPolylineBounds(polyline As AcadLWPolyline) As Bounds Dim bounds As New Bounds Dim minPoint As Object = Nothing Dim maxPoint As Object = Nothing polyline.GetBoundingBox(minPoint, maxPoint) bounds.MinX = minPoint(0) bounds.MinY = minPoint(1) bounds.MaxX = maxPoint(0) bounds.MaxY = maxPoint(1) Return bounds End Function ' 边界结构体 Private Structure Bounds Public MinX As Double Public MinY As Double Public MaxX As Double Public MaxY As Double End Structure End Module 以上代码的排列组合不对,先行后列X逆序是右上角向左下角的,先行后列Y逆序是左下角向右上角的,先行后列X逆序Y逆序是右下角向左上角的,正序逻辑相反;先列后行X逆序是右上角向左下角的,先列后行Y逆序是左下角向右上角的,先列后行X逆序Y逆序是右下角向左上角的,正序逻辑相反;请把所有组合搞对,确保每种组合容差生效。请修改后,在每行代码后注释,分别用1个模块回答完整,不要省略。
最新发布
08-11
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值