2015-08-17 2 views
1

Я пытаюсь нарисовать сетку внутри окна game_width=640 и game_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)) 

идея заключается в том, чтобы избежать целочисленного деления, сделать флоат деление, умножение на я, как раньше, и отбрасывать результат обратно в междунар. Это хорошо работает, без лишней ячейки в конце!

enter image description here

Что сводит меня с умом, это уравнение:

i * game_height/numcells 

, который, кажется, имеет тот же эффект, как и в предыдущем уравнении, но, конечно, с дополнительным преимуществом не делает никакой отливки. Я не могу понять, почему это не страдает целыми делениями в первом уравнении.

Обратите внимание, что математически: X * (Y/Z) == X * Y/Z Таким образом, существует определенная проблема с целым делением в первом уравнении.

Here's a video смотреть эти 3 уравнения в окне просмотра отладчика.

Вы можете видеть увеличение разрыва между результатом первого уравнения против второго и третьего (которое всегда имело тот же результат), поскольку i увеличивается.

Почему 3-е уравнение дает правильные результаты в качестве второго уравнения и не страдает от погрешности интегрального деления в первом уравнении? Я просто не могу обернуть вокруг себя ...

Любая помощь приветствуется.

ответ

2

Ответ выполнен в порядке выполненных операций. Первое уравнение

int y = i * (game_height/numcells); 

выполняет деление первого и увеличивает ошибку округления путем умножения с i. Чем дальше вы двигаетесь вниз/вправо, тем больше будет скопирована ошибка округления.

Последнее уравнение

int y = i * game_height/numcells; 

оценивается слева направо. Относительная ошибка уменьшается, поскольку вы делите большие числа (i * game_height). У вас все еще есть ошибка округления, но она не накапливается. Тот факт, что вы не закончите с дополнительным пространством при окончательной оценке, заключается в том, что i равен numcells, по существу отменяя друг друга. В последней итерации вы всегда увидите y == game_height.

Использование операций с плавающей запятой по-прежнему является более точным: хотя ошибка округления с использованием целочисленной математики находится в интервале [0 .. numcells) для каждой строки, математика с плавающей запятой уменьшает ее до [0 .. 1). Вы увидите более равномерно распределенные строки, используя математику с плавающей запятой.


Примечание: в Windows вы можете использовать MulDiv вместо целочисленного уравнения, чтобы предотвратить распространенные ошибки, такие как переходные переполнения.

Смежные вопросы