软件简介

点击 “计算” 按钮开始计算,如果已经计算完成,再次点击这个按钮可以执行清除计算结果重新计算。
窗口下端显示的缓存文件名和存放位置,删除这个文件可以清除计算结果,这个文件在每个电脑里面的存放位置可能不同。

窗口下面显示计算过程的进度条,当计算进度达到一定程度,开始刷新显示,此时就可以来回翻阅计算结果了。

当计算结束,进度条消失,显示一共找到的素数的个数,“计算素数” 按钮恢复可以点击状态,显示刷新为完整的计算结果。

拖动鼠标可以定义选择范围,利用快捷键 “Ctrl + C” 或鼠标右键点击选择内容,选择 “复制” 把所选数据复制到剪贴板,可以粘贴到其他文字文件里面。
利用筛选法求出 10000000000 以内所有的素数
由于计算时间比较长,在线程里面进行计算。
计算素数的类 TPrimeNumbers 从 TThread 线程类继承,算法写在 Execute 成员函数里面。
TPrimeProgress 类作为 TPrimeNumbers 类的构造函数的参数,用来存放显示计算的进度和存放缓存文件的文件名。
计算结果存放在 TPrimeProgress 的成员 FileName 文件名指定的文件里面。
TPrimeNumbers 的成员 _ulFileBufSize 指定计算结果缓存的大小,计算结果存放在这个缓存里面,这个缓存满了进行存盘和清空,继续存放接下来的计算结果,此时主线程就打开这个缓存文件进行刷新显示数据了,一边计算一边刷新显示,可以来回翻阅计算结果显示的表格,一直到计算结束,表格刷新为完整的计算结果。
UnitPrimeNumbers.h |
//---------------------------------------------------------------------------
// 计算 1,000,000,000 以内的素数,Victor Chen, http://www.cppfans.com/ 版权所有
#ifndef UnitPrimeNumbersH
#define UnitPrimeNumbersH
//---------------------------------------------------------------------------
#include <System.Classes.hpp>
//---------------------------------------------------------------------------
class TPrimeProgress
{
public:
unsigned long long MaxNumber;
unsigned long long Progress;
bool Working;
wchar_t FileName[_MAX_PATH];
void Clear(void);
TPrimeProgress();
};
//---------------------------------------------------------------------------
class TPrimeNumbers : public TThread
{
public:
__fastcall TPrimeNumbers(TPrimeProgress &Progress);
__fastcall ~TPrimeNumbers();
protected:
void __fastcall Execute(void);
private:
TPrimeProgress &_Progress;
void CreatePrimeFile(void);
void SaveToPrimeFile(unsigned long long *lpullFileBuffer, int iFileBufCount);
void ClosePrimeFile(void);
FILE *_fpPrimeFile;
};
//---------------------------------------------------------------------------
#endif
//--------------------------------------------------------------------------- |
UnitPrimeNumbers.cpp |
//---------------------------------------------------------------------------
// 计算 1,000,000,000 以内的素数,Victor Chen, http://www.cppfans.com/ 版权所有
#include <share.h>
#pragma hdrstop
#include "UnitPrimeNumbers.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
/////////////////////////////// TPrimeProgress //////////////////////////////
//---------------------------------------------------------------------------
TPrimeProgress::TPrimeProgress()
{
MaxNumber = 0;
Progress = 0;
Working = false;
}
//---------------------------------------------------------------------------
void TPrimeProgress::Clear(void)
{
MaxNumber = 0;
Progress = 0;
Working = false;
}
//---------------------------------------------------------------------------
/////////////////////////////// TPrimeNumbers ///////////////////////////////
//---------------------------------------------------------------------------
__fastcall TPrimeNumbers::TPrimeNumbers(TPrimeProgress &Progress)
: _Progress(Progress)
{
FreeOnTerminate = true;
_fpPrimeFile = NULL;
CreatePrimeFile();
_Progress.Working = true; // 正在计算
}
//---------------------------------------------------------------------------
__fastcall TPrimeNumbers::~TPrimeNumbers()
{
ClosePrimeFile();
_Progress.Working = false; // 计算结束
}
//---------------------------------------------------------------------------
void __fastcall TPrimeNumbers::Execute(void)
{
unsigned long long &ullMaxNumber = _Progress.MaxNumber;
unsigned long long &pn = _Progress.Progress;
int _iFileBufCount = 0; // 文件缓存里面的数据个数
int _iFileBufSize = 10000000; // 文件缓存的大小 (最大数据个数) 10M*8 = 80M
unsigned long long *lpullFileBuffer = new unsigned long long[_iFileBufSize];
lpullFileBuffer[_iFileBufCount++] = 2;
unsigned long long ullMaxCheck = std::sqrt(ullMaxNumber)+0.5;
unsigned long long ullFilterSize = ullMaxNumber/2/8 + 1;
char *cPrimeFilter = new char[ullFilterSize];
memset(cPrimeFilter, 0, ullFilterSize);
for(pn=3; pn<=ullMaxNumber; pn+=2) // 检查 pn 是否为素数
{
unsigned long ulOfs = pn/2/8;
unsigned char ulBit = 1<<((pn/2)%8);
if(!(cPrimeFilter[ulOfs]&ulBit))
{
lpullFileBuffer[_iFileBufCount++] = pn;
if(pn<=ullMaxCheck)
{
int iSaveCount = _iFileBufSize<100?_iFileBufSize:100;
if(_iFileBufCount>=iSaveCount)
{
SaveToPrimeFile(lpullFileBuffer, _iFileBufCount);
_iFileBufCount = 0;
}
unsigned long long ulStep = pn << 1;
for(unsigned long long m=pn; m<=ullMaxNumber; m+=ulStep)
{
ulOfs = m/2/8;
ulBit = 1<<((m/2)%8);
cPrimeFilter[ulOfs] |= ulBit; // 把 pn 的倍数加入过滤器
}
}
else
{
if(_iFileBufCount>=_iFileBufSize)
{
SaveToPrimeFile(lpullFileBuffer, _iFileBufCount);
_iFileBufCount = 0;
}
}
}
}
SaveToPrimeFile(lpullFileBuffer, _iFileBufCount);
delete[] cPrimeFilter;
delete[] lpullFileBuffer;
}
//---------------------------------------------------------------------------
void TPrimeNumbers::CreatePrimeFile(void)
{
if(!_fpPrimeFile)
_fpPrimeFile = std::_wfsopen(_Progress.FileName, L"wb", SH_DENYNONE);
if(_fpPrimeFile)
_fseeki64(_fpPrimeFile, 0, SEEK_SET);
}
//---------------------------------------------------------------------------
void TPrimeNumbers::SaveToPrimeFile(unsigned long long *lpullFileBuffer, int iFileBufCount)
{
if(_fpPrimeFile)
{
std::fwrite(lpullFileBuffer, sizeof(*lpullFileBuffer), iFileBufCount, _fpPrimeFile);
std::fflush(_fpPrimeFile);
}
}
//---------------------------------------------------------------------------
void TPrimeNumbers::ClosePrimeFile(void)
{
if(_fpPrimeFile)
{
std::fclose(_fpPrimeFile);
_fpPrimeFile = NULL;
}
}
//--------------------------------------------------------------------------- |
显示数据表格
显示表格的类 TVictorPrimeGrid 从 TDrawGrid 表格类继承,增加显示数据和把选择的数据复制到剪贴板功能。
UnitPrimeGrid.h |
//---------------------------------------------------------------------------
// 显示素数数据的表格,Victor Chen, http://www.cppfans.com/ 版权所有
#ifndef UnitPrimeGridH
#define UnitPrimeGridH
//---------------------------------------------------------------------------
#include <Vcl.Grids.hpp>
//---------------------------------------------------------------------------
class TVictorPrimeGrid : public TDrawGrid
{
public:
typedef void __fastcall (__closure *TOnGetPrimeText)(System::TObject *Sender, int ACol, int ARow, System::UnicodeString &AText);
__property TOnGetPrimeText OnGetPrimeText = { read = _lpfnGetPrimeText, write = _lpfnGetPrimeText };
bool IsSelCell(int ACol, int ARow);
void GetSelCells(int &iSelStartCol, int &iSelStartRow, int &iSelEndCol, int &iSelEndRow);
void CopyDataToClipboard(void);
__fastcall TVictorPrimeGrid(System::Classes::TComponent *AOwner);
protected:
virtual bool __fastcall SelectCell(int ACol, int ARow);
virtual void __fastcall SelectionMoved(const TGridRect &OldSel);
virtual void __fastcall DrawCell(int ACol, int ARow, const System::Types::TRect &ARect, TGridDrawState AState);
virtual void __fastcall GetPrimeText(int ACol, int ARow, System::UnicodeString &AText);
private:
TOnGetPrimeText _lpfnGetPrimeText;
COLORREF MixedRgbColor(COLORREF c0, COLORREF c1, int t);
void DrawGradientRect(COLORREF crTop, COLORREF crBottom, const System::Types::TRect &ARect);
};
//---------------------------------------------------------------------------
#endif
//--------------------------------------------------------------------------- |
UnitPrimeGrid.cpp |
//---------------------------------------------------------------------------
// 显示素数数据的表格,Victor Chen, http://www.cppfans.com/ 版权所有
#include <Vcl.Clipbrd.hpp>
#pragma hdrstop
#include "UnitPrimeGrid.h"
//---------------------------------------------------------------------------
#pragma package(smart_init)
//---------------------------------------------------------------------------
////////////////////////////// TVictorPrimeGrid /////////////////////////////
//---------------------------------------------------------------------------
__fastcall TVictorPrimeGrid::TVictorPrimeGrid(System::Classes::TComponent *AOwner)
: TDrawGrid(AOwner)
{
_lpfnGetPrimeText = NULL;
Options = Options << goRangeSelect << goColSizing << goThumbTracking;
DefaultColWidth = 67;
DefaultRowHeight = 20;
ColCount = 11;
RowCount = 2;
}
//---------------------------------------------------------------------------
bool TVictorPrimeGrid::IsSelCell(int ACol, int ARow)
{
int iSelStartCol, iSelStartRow, iSelEndCol, iSelEndRow;
GetSelCells(iSelStartCol, iSelStartRow, iSelEndCol, iSelEndRow);
return (ARow>iSelStartRow || (ARow==iSelStartRow && ACol>=iSelStartCol)) &&
(ARow<iSelEndRow || (ARow==iSelEndRow && ACol<=iSelEndCol ));
}
//---------------------------------------------------------------------------
void TVictorPrimeGrid::GetSelCells(int &iSelStartCol, int &iSelStartRow, int &iSelEndCol, int &iSelEndRow)
{
iSelStartCol = Selection.Left;
iSelStartRow = Selection.Top;
iSelEndCol = Selection.Right;
iSelEndRow = Selection.Bottom;
if(iSelStartRow!=iSelEndRow)
{
if((iSelStartRow==Row && iSelEndCol==Col) || (iSelEndRow==Row && iSelStartCol==Col))
{
iSelStartCol ^= iSelEndCol;
iSelEndCol ^= iSelStartCol;
iSelStartCol ^= iSelEndCol;
}
}
}
//---------------------------------------------------------------------------
bool __fastcall TVictorPrimeGrid::SelectCell(int ACol, int ARow)
{
bool bRetVal = TDrawGrid::SelectCell(ACol, ARow);
Invalidate();
return bRetVal;
}
//---------------------------------------------------------------------------
void __fastcall TVictorPrimeGrid::SelectionMoved(const TGridRect &OldSel)
{
TDrawGrid::SelectionMoved(OldSel);
Invalidate();
}
//---------------------------------------------------------------------------
void __fastcall TVictorPrimeGrid::DrawCell(int ACol, int ARow, const System::Types::TRect &ARect, TGridDrawState AState)
{
TDrawGrid::DrawCell(ACol, ARow, ARect, AState);
UnicodeString sText;
if(ARow==0)
{
if(ACol>0)
sText.sprintf(L"%d",ACol);
else
sText = L"序号";
}
else if(ACol==0)
{
sText.sprintf(L"%d",(ARow-1)*10);
}
GetPrimeText(ACol, ARow, sText);
TColor cOldFontColor = Canvas->Font->Color;
TColor cOldBrushColor = Canvas->Brush->Color;
TBrushStyle bsOldBrushStyle = Canvas->Brush->Style;
bool bFocusedRow = ARow == Row;
bool bFocusedCol = ACol == Col;
bool bSelected = IsSelCell(ACol, ARow);
UINT cTxtAlign = DT_CENTER;
TColor cTxtColor = clBlack;
TColor cBkColor = clWhite;
if(bSelected)
{
cTxtColor = clWhite;
cBkColor = clBlue;
}
else if(bFocusedRow)
{
cBkColor = TColor(RGB(192,223,255));
}
else if(bFocusedCol)
{
cBkColor = TColor(RGB(255,223,245));
}
if(ARow && ACol) // 数据
{
cTxtAlign = DT_RIGHT;
Canvas->Brush->Color = cBkColor;
Canvas->Brush->Style = bsSolid;
Canvas->FillRect(ARect);
}
else // 标题栏或序号栏
{
cTxtColor = clBlack;
COLORREF crTop = RGB(255,255,255);
COLORREF crBottom = RGB(192,192,192);
if(bFocusedRow || bFocusedCol)
{
COLORREF crBkgnd = Graphics::ColorToRGB(cBkColor);
crTop = MixedRgbColor(crTop , crBkgnd, 160);
crBottom = MixedRgbColor(crBottom, crBkgnd, 160);
}
DrawGradientRect(crTop, crBottom, ARect);
}
TRect trc(ARect.Left+2, ARect.Top, ARect.Right-2, ARect.Bottom);
Canvas->Font->Color = cTxtColor;
Canvas->Brush->Style = bsClear;
::DrawText(Canvas->Handle, sText.c_str(), sText.Length(), &trc, cTxtAlign|DT_VCENTER|DT_SINGLELINE);
Canvas->Brush->Style = bsOldBrushStyle;
Canvas->Brush->Color = cOldBrushColor;
Canvas->Font->Color = cOldFontColor;
}
//---------------------------------------------------------------------------
COLORREF TVictorPrimeGrid::MixedRgbColor(COLORREF c0, COLORREF c1, int t)
{
int r0 = GetRValue(c0), g0 = GetGValue(c0), b0 = GetBValue(c0);
int r1 = GetRValue(c1), g1 = GetGValue(c1), b1 = GetBValue(c1);
int r = r1 + (r0-r1)*t/255;
int g = g1 + (g0-g1)*t/255;
int b = b1 + (b0-b1)*t/255;
return RGB(r,g,b);
}
//---------------------------------------------------------------------------
void TVictorPrimeGrid::DrawGradientRect(COLORREF crTop, COLORREF crBottom, const System::Types::TRect &ARect)
{
int r0 = GetRValue(crTop ), g0 = GetGValue(crTop ), b0 = GetBValue(crTop );
int r1 = GetRValue(crBottom), g1 = GetGValue(crBottom), b1 = GetBValue(crBottom);
int h = ARect.Height();
for(int i=0; i<h; i++)
{
int y = ARect.Top + i;
int r = r0 + (r1-r0)*i/h;
int g = g0 + (g1-g0)*i/h;
int b = b0 + (b1-b0)*i/h;
Canvas->Pen->Color = TColor(RGB(r,g,b));
Canvas->MoveTo(ARect.Left , y);
Canvas->LineTo(ARect.Right, y);
}
}
//---------------------------------------------------------------------------
void __fastcall TVictorPrimeGrid::GetPrimeText(int ACol, int ARow, System::UnicodeString &AText)
{
if(_lpfnGetPrimeText)_lpfnGetPrimeText(this, ACol, ARow, AText);
}
//---------------------------------------------------------------------------
void TVictorPrimeGrid::CopyDataToClipboard(void)
{
TClipboard *lpcb = Clipboard();
int iSelStartCol, iSelStartRow, iSelEndCol, iSelEndRow;
GetSelCells(iSelStartCol, iSelStartRow, iSelEndCol, iSelEndRow);
int iCount = 0;
int iRow = iSelStartRow, iCol = iSelStartCol;
UnicodeString sText, sNumber;
bool bNewLine = true;
while(IsSelCell(iCol, iRow) && (++iCount<=5000))
{
GetPrimeText(iCol, iRow, sNumber);
if(sNumber.IsEmpty())
break;
if(!sText.IsEmpty())
sText += bNewLine ? L",\r\n" : L", ";
sText += sNumber;
bNewLine = ++iCol > 10;
if(bNewLine)
{
iCol=1;
iRow++;
}
}
lpcb->AsText = sText;
}
//--------------------------------------------------------------------------- |
软件和源码下载
压缩包内容 |
Win32\PrimeNumbers.exe |
32位执行文件 |
Win64\PrimeNumbers.exe |
64位执行文件 |
Source\*.* |
程序源码 (C++ Builder 10.2) |
|
下载求出 10,000,000,000 以内所有的素数 (Win32/Win64) 软件 + 源码,版本 1.1.2017.10220
(2,082,705 字节,下载
3800
次)
相关连接:计算圆周率 Pi (π) 值, 精确到小数点后 10000 位
|