c++ - 水平/垂直均匀分布网格单元?

标签 c++ winapi math integer-division

我正在尝试在 game_width=640game_height=480 的窗口内绘制网格。网格单元的数量是预定义的。我想在水平和垂直方向上均匀分布单元格。

void GamePaint(HDC dc)
{
    int numcells = 11;
    for(int i = 1; i <= numcells; i++)
    {
        int y = <INSERT EQUATION>;
        MoveToEx(dc, 0, y, NULL);
        LineTo(dc, game_width, y);
    }

    // solving the horizontal equation will in turn solve the vertical one so no need to show the vertical code
}

我想到的第一个等式是:

i * (game_height / numcells)

这背后的概念是将总高度除以单元格数以获得偶数单元格大小,然后在循环的每次迭代中将其乘以 i 以获得正确的 y 坐标水平线的起点。

问题在于它似乎在最后留下了一个额外的小单元:

enter image description here

我认为这一定与积分除法有关,所以我们得出第二个等式:

(int)(i * ((float)game_height / numcells))

想法是避免整数除法,进行 float 除法,像以前一样乘以 i,然后将结果转换回 int。这很好用,最后没有额外的小蜂窝!

enter image description here

让我发疯的是这个等式:

i * game_height / numcells

这似乎与前面的等式具有相同的效果,但当然还有不进行任何转换的额外好处。我不明白为什么这不会受到第一个等式中整数除法问题的影响。

请注意,数学上:X * (Y/Z) == X * Y/Z 所以第一个方程的整数除法肯定有问题。

Here's a video在调试器观察窗口中观察这 3 个等式。

随着 i 的增加,您可以看到第一个方程的结果与第二个和第三个方程(结果始终相同)之间的差距越来越大。

为什么第三个方程给出的结果与第二个方程一样正确,而没有受到第一个方程中积分除法错误的影响?我似乎无法理解它...

感谢任何帮助。

最佳答案

答案是按照执行操作的顺序。第一个方程

int y = i * (game_height / numcells);

先进行除法,然后乘以i放大舍入误差。向下/向右移动得越远,累积的舍入误差就越大。

最后一个等式

int y = i * game_height / numcells;

从左到右计算。随着您除以较大的数字 (i * game_height),相对误差会变小。您仍然有舍入误差,但它不会累积。事实上,您在最终评估时没有得到额外空间的事实是,i 等于 numcells,本质上相互抵消。您将始终在最终迭代中看到 y == game_height

使用浮点运算仍然更准确:虽然使用整数数学的舍入误差在每行的区间 [0 .. numcells) 中,但 float 学将其减少到 [ 0 .. 1)。使用 float 学,您会看到分布更均匀的线条。


注意:在 Windows 上您可以使用 MulDiv而不是整数方程,以防止常见错误,例如 transient 溢出。

关于c++ - 水平/垂直均匀分布网格单元?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/32041796/

相关文章:

ruby-on-rails - 在 Ruby on Rails 上使用表行值进行数学运算

c++ - Qt/C++ 基于比较的信号调度的优雅方式

c++ -/lib64/libstdc++.so.6 : version `GLIBCXX_3.4.20' not found

c++ - 编译器控件如何帮助在 C++ 中分配和释放内存?

c# - 进入外部应用程序的消息循环

winapi - 在 Windows 10 上找不到 SDK "Microsoft.VCLibs, Version=14.0"

c++ - 删除移动到容器的对象时的SIGABRT

windows - 如何在所有者绘制菜单中绘制自己的子菜单箭头(并防止窗口在我的顶部绘制其箭头)

arrays - 二维数组中的单个元素的数学运算 - Swift

c++ - Eigen ,错误地使用了不同类型的逗号初始化程序