我正在制作一个用C显示正弦图的程序, 这是程序的一小部分
LRESULT CALLBACK WndProc(HWND hwnd, UINT message, WPARAM wParam, LPARAM lParam)
{
static int cxClient, cyClient;
HDC hdc;
int i;
PAINTSTRUCT ps;
POINT apt[NUM];
switch (message)
{
case WM_SIZE:
cXClient = LOWORD(lParam);
cyClient = HIWORD(lParam);
return 0;
case WM_PAINT:
hdc = BeginPaint(hwnd, &ps);
MoveToEx(hdc, 0, cyClient / 2, 0);
LineTo(hdc, cxClient, cyClient / 2);
for (i = 0; i < NUM; i++)
{
apt[i].x = i * cxClient / NUM;
apt[i].y = (int) (height / 2 * (1 - sin(TWOPI * i / NUM)));
}
Polyline(hdc, apt, NUM);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, message, wParam, lParam);
}
其中NUM设置为1000,cxClient是低字的客户区宽度,cyClient是高字的客户区高度,TWOPI全局定义为(2 * 3.1459)
我的程序问题是
1.我无法理解 apt [i] .x和apt [i] .y (包括正弦形式)这一行。
2.当我将TWOPI定义为 #define TWOPI(2 *(22/7))而不是( #define TWOPI(2 * 3.1459))时,图形是方形的,但两者都是相同的,相反,这更准确,为什么会发生这种情况。
书中没有解释这些事情,所以我问你。
答案 0 :(得分:1)
我将从2开始,这基本上是What is the behavior of integer division?的副本。
简而言之:除法运算符获取两个操作数并返回一个大且精确到足以容纳任何操作数的类型的值。因此,整数除法将始终产生整数结果,因为任何整数都足够精确以容纳整数。如您所知,整数除法可能会产生实际值,因此至少有一个操作数必须是实数。例如#define TWOPI (2*(22.0/7)) // implicit conversion
或#define TWOPI (2*((float)22/7) // explicit conversion
。这解释了方形图
[]
运算符访问数组的成员,并为offseted为0的元素提供元素的索引(array[0]
,从而产生第一个元素)。使用.
运算符(或->
)访问结构,提供元素的名称。apt[i]
基本上意味着“从i”中取出数组apt
中的元素,或者换言之“从名为i+1
的数组中获取apt
元素”。添加.x
表示“没问题,因为apt
的元素包含其他容器,会使用名为x
的元素”,这很方便地表示正弦波中点的x坐标。编辑[解释数学]:
1. 1-sin()
。正弦函数的值范围为R = [-1;1]
,因此为1-R = [2;0]
。这导致函数被反转(对正弦没有“视觉”效应)并且向上移动到正值。在实践中,这允许添加高度乘数而不处理负值。即,该功能仅从零点“长大”,并且不会从中心点向两个方向“扩展”
2. sin()
内的内容。您正在迭代i从0到NUM
。在sin()
内,你有一些乘以i/NUM
的东西。如果你在纸上分析了那么你会在每次迭代TWOPI
中得到它乘以1 / 10,2 / 10,3 / 10等。sin()
期望它的参数以弧度为单位并且是“满的“正弦波(一个周期)可在区域[0; 2π。所以乘以2 PI基本上意味着你代表一个正弦波周期。将其更改为4 PI将导致2个正弦波周期。