主页C++ Builder 源码求出 10,000,000,000 以内的所有的素数,显示在表格里面
Victor 串口控件
 • 最新版本 (VCL/FMX)
 • 常见问题及解决方法
 • 以往版本串口控件
控件安装方法
 • XE6 ~ C10 (CX)
 • XE2 ~ XE5
 • 2007/2009/2010/XE
 • BCB5, BCB6
使用简介
串口控件详细说明
串口调试工具
C++ Builder 资料
C++ Builder 编程技巧
C++ Builder 操作指南
C++ Builder 参考手册
C++ Builder 资源
控件
SDK 开发库
源码
软件发布
更新动态
网站更新记录
网友留言/技术支持
求出 10,000,000,000 以内的所有的素数,显示在表格里面
软件简介
利用筛选法求出 10000000000 以内所有的素数
显示数据表格
软件和源码下载

软件简介

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

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

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

拖动鼠标可以定义选择范围,利用快捷键 “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 位


C++ 爱好者 -- Victor Chen 的个人网站 www.cppfans.com 辽ICP备11016859号