当前位置:  开发笔记 > 编程语言 > 正文

为什么我们的c#图形代码不再工作?

如何解决《为什么我们的c#图形代码不再工作?》经验,为你挑选了2个好方法。

情况如下:

我们有一些通用的图形代码,我们用于其中一个项目.在对代码进行一些清理之后,似乎某些东西不再起作用了(图形输出看起来完全错误).

我对提供正确输出的代码的最后一个版本运行了一个diff,看起来我们改变了我们的一个函数,如下所示:

static public Rectangle FitRectangleOld(Rectangle rect, Size targetSize)
{
    if (rect.Width <= 0 || rect.Height <= 0)
    {
        rect.Width = targetSize.Width;
        rect.Height = targetSize.Height;
    }
    else if (targetSize.Width * rect.Height > 
        rect.Width * targetSize.Height)
    {
        rect.Width = rect.Width * targetSize.Height / rect.Height;
        rect.Height = targetSize.Height;
    }
    else
    {
        rect.Height = rect.Height * targetSize.Width / rect.Width;
        rect.Width = targetSize.Width;
    }

    return rect;
}

static public Rectangle FitRectangle(Rectangle rect, Size targetSize)
{
    if (rect.Width <= 0 || rect.Height <= 0)
    {
        rect.Width = targetSize.Width;
        rect.Height = targetSize.Height;
    }
    else if (targetSize.Width * rect.Height > 
             rect.Width * targetSize.Height)
    {
        rect.Width *= targetSize.Height / rect.Height;
        rect.Height = targetSize.Height;
    }
    else
    {
        rect.Height *= targetSize.Width / rect.Width;
        rect.Width = targetSize.Width;
    }

    return rect;
}

我们所有的单元测试都是通过的,代码中的任何内容都没有改变,除了一些语法快捷方式.但就像我说的那样,输出是错误的.我们可能只是回到旧代码,但我很好奇是否有人知道这里发生了什么.

谢谢.



1> Daniel LeChe..:

听起来你没有足够的单元测试:]

不幸的是,你的陈述

"代码中的任何内容都没有改变,除了一些语法快捷方式"

是错的,我猜这就是问题所在.(这肯定是你的一个问题!)

是,

a *= b;

相当于

a = a * b;

a *= b / c;

是不一样的

a = a * b / c;

代替

a *= b / c;    // equivalent to a = a * (b / c)
a = a * b / c; // equivalent to a = (a * b) / c

(参见msdn上的c#运算符优先级)

当你的目标高度不是原始矩形高度的精确倍数(或者宽度相同)时,我猜你遇到了麻烦.

然后你最终会遇到以下情况:

我们假设rect.Size =(8,20),targetSize =(15,25)

使用原始方法,您将得出以下计算结果:

rect.Width     = rect.Width * targetSize.Height / rect.Height;
//             = 8          * 25                / 20
//             = 200 / 20 (multiplication happens first)
//             = 10
// rect.Width  = 10

使用您的新代码,您就拥有了

rect.Width    *= targetSize.Height / rect.Height;
//            *= 25 / 20
//            *= 1 (it's integer division!)
// rect.Width  = rect.Width * 1
//             = 8
// rect.Width  = 8

这是不一样的.(如果目标大小小于原始大小,情况会更糟;在这种情况下,整数除法将导致其中一个维度为0!)

如果"[你的]单元测试全部通过"那么你肯定需要一些额外的测试,特别是那些处理非整数倍的测试.

另请注意您的计算方法

else if(targetSize.Width * rect.Height > 
        rect.Width * targetSize.Height)

不可靠; 对于非常大的矩形,它有可能溢出并给你不正确的结果.作为乘法的一部分,你最好能够投射到更大的类型(即长).(再次,应该有一些单元测试这种效果)

希望有所帮助!



2> strager..:

如果Rectangle.Width和Rectangle.Height是整数,则以下两行不同:

rect.Width = rect.Width * targetSize.Height / rect.Height;
rect.Width *= targetSize.Height / rect.Height;

第一行按顺序执行乘法,除法,转换为int,然后赋值.第二个执行除法,转换为int,乘法,然后赋值.问题是,在你的非工作代码中,你的除法在乘法之前被转换为整数.

保留原始代码或强制除法为浮点.

编写更好的单元测试来检查此问题.(尝试没有偶数倍的宽度/高度组合(例如素数).)

推荐阅读
小色米虫_524
这个屌丝很懒,什么也没留下!
DevBox开发工具箱 | 专业的在线开发工具网站    京公网安备 11010802040832号  |  京ICP备19059560号-6
Copyright © 1998 - 2020 DevBox.CN. All Rights Reserved devBox.cn 开发工具箱 版权所有