浮点数精度问题(60分)
非常老的一个话题, 以为搞懂了,没想到在实战中 
case WM_PAINT:
{
HDC hdc = BeginPaint(hWnd, &ps);
RECT rc;
GetClientRect(hWnd,&rc);
SetViewportOrgEx(hdc,rc.right/2,rc.bottom/2,NULL);
float x=-360.0f;
float y=0.0f;
MoveToEx(hdc,x,0,NULL);
while(x<360.0f)
{
y=sin(x/57.3)*100;
LineTo(hdc,x,y);
MoveToEx(hdc,x,y,NULL);
x+=1.5f;
}
for(x=-360.0f;x<=360.0f;x+=90.0f)
{
TCHAR buf[20]={0};
y=sin(x/57.3)*100;
if(abs(y-0.0f)<0.00001f)
{
_stprintf(buf,_T("x=%d度;y=%f"),(int)x,y);
TextOut(hdc,x+4.0f,y+8.0f,buf,lstrlen(buf));
}
else if(abs(y-100.0f)<0.00001f)
{
_stprintf(buf,_T("x=%d度;y=%f"),(int)x,y);
TextOut(hdc,x+4.0f,y-8.0f,buf,lstrlen(buf));
}
}
EndPaint(hWnd, &ps);
return 0;
}
break;
需求:绘制一条正弦曲线,绘制后,在一些点的附近标注x,y的值。
(这些点为:y=0,y=+-100的点)
问题: 曲线绘正确了,但是 标注x,y的值不对,
截图吧:
很明显,少了一些标注了,比如y=-100.0f的地方就没有标注,怎么回事呢?
[解决办法]
当 y== -100.0f的时候,
下面两条判断语句,走哪一条啊?呵呵。
if(abs(y-0.0f)<0.00001f)
{
。。。
}
else if(abs(y-100.0f)<0.00001f)//走这条吗?-100 - 100 =?
{
。。。
}
另外对于浮点数求绝对值最好用fabs
[解决办法]
#include <windows.h>
#include <stdio.h>
#include <tchar.h>
#include <math.h>
TCHAR szAppName[] = TEXT("Test");
LRESULT CALLBACK TestWinProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
);
int WINAPI WinMain(
HINSTANCE hInstance, // handle to current instance
HINSTANCE hPrevInstance, // handle to previous instance
LPSTR lpCmdLine, // command line
int nCmdShow // show state
)
{
WNDCLASS wndcls;
HWND hwnd;
BOOL bRet;
MSG msg;
hInstance = hInstance;
wndcls.cbClsExtra = 0;
wndcls.cbWndExtra = 0;
wndcls.hbrBackground = (HBRUSH)GetStockObject(WHITE_BRUSH);
wndcls.hCursor = LoadCursor(NULL, IDC_ARROW);
wndcls.hIcon = LoadIcon(NULL, IDI_APPLICATION);
wndcls.hInstance = hInstance;
wndcls.lpfnWndProc = TestWinProc;
wndcls.lpszClassName = szAppName;
wndcls.lpszMenuName = NULL;//无菜单
wndcls.style = CS_VREDRAW
[解决办法]
CS_HREDRAW;
if (!RegisterClass(&wndcls))
{
MessageBox(NULL, TEXT("此程序需要在WINDOWS NT操作系统下运行!"),
szAppName, MB_ICONERROR);
return 0;
}
hwnd = CreateWindow(szAppName, TEXT("Test"), WS_OVERLAPPEDWINDOW, CW_USEDEFAULT,
CW_USEDEFAULT, CW_USEDEFAULT, CW_USEDEFAULT, NULL, NULL, hInstance, NULL);
ShowWindow(hwnd, SW_SHOWNORMAL);
UpdateWindow(hwnd);
while( (bRet = GetMessage( &msg, NULL, 0, 0 )) != 0)
{
if (-1 == bRet)
{
// handle the error and possibly exit
}
else
{
TranslateMessage(&msg);
DispatchMessage(&msg);
}
}
return 0;
}
LRESULT CALLBACK TestWinProc(
HWND hwnd, // handle to window
UINT uMsg, // message identifier
WPARAM wParam, // first message parameter
LPARAM lParam // second message parameter
)
{
static int cxChar;
HDC hdc;
PAINTSTRUCT ps;
TEXTMETRIC tm;
RECT rc;
float x=-360.0f; float y=0.0f;// for draw sine line
switch(uMsg)
{
case WM_CREATE:
hdc = GetDC(hwnd);
SelectObject(hdc, GetStockObject(SYSTEM_FIXED_FONT));
GetTextMetrics(hdc, &tm);
cxChar = tm.tmAveCharWidth;
return 0;
case WM_PAINT:
{
hdc = BeginPaint(hwnd, &ps);
GetClientRect(hwnd,&rc);
SetMapMode(hdc, MM_LOENGLISH);
SetViewportOrgEx(hdc,rc.right/2,rc.bottom/2,NULL);
//draw y=100sin(x) sine line
MoveToEx(hdc,(int)(x),0,NULL);
while(x<360.0f)
{
y=(float)sin(x/57.3)*100;
LineTo(hdc,(int)(x),(int)y);
x+=1.5f;
}
for(x=-360.0f;x<=360.0f;x+=90.0f)
{
TCHAR buf[40] = {0};
y=(float)sin(x/57.3)*100;
if(fabs(y-0.0f)<0.05f)
{
_stprintf(buf,_T("x=%d度;y=%f"),(int)x,y);
TextOut(hdc,x,y,buf,lstrlen(buf));
}
else if(fabs(y-100.0f)<0.05f)
{
_stprintf(buf,_T("x=%d度;y=%f"),(int)x,y);
TextOut(hdc,x,y,buf,lstrlen(buf));
}
else if(fabs(y+100.0f)<0.05f)
{
_stprintf(buf,_T("x=%d度;y=%f"),(int)x,y);
TextOut(hdc,x,y,buf,lstrlen(buf));
}
}
EndPaint(hwnd, &ps);
return 0;
}
return 0;
case WM_CLOSE:
DestroyWindow(hwnd);
return 0;
case WM_DESTROY:
PostQuitMessage(0);
return 0;
}
return DefWindowProc(hwnd, uMsg, wParam, lParam);
}