of {$slidecount} ½ {$title} ATZJG.NET {$author}

首页






C++ 上机实验
参考书: 钱能 著 C++ 程序设计教程实验指导


Haifeng Xu


(hfxu@yzu.edu.cn)

目录

Codeblocks

Codeblocks

Code::Blocks 是一个开源的(open source)、跨平台的(cross platform)集成开发环境(IDE), 适合 C、C++ 和 Fortran.

官方网站: http://www.codeblocks.org/

目前的最新版本是 Code::Blocks 17.12 (2019-02-21)

启动 Code::Blocks, 会显示

然后是 Tip 窗口

CodeBlocks 的主界面是这样的

Hello World 程序

Hello World 程序

创建一个新项目, 点击 Create a new project

选择 控制台应用程序(Console application)

下一步可以设置跳过

选择 C++

输入项目的标题, 这里我们输入 helloworld

选择编译器, 这里我们选择 GNU 的 GCC 编译器.

然后得到下面的界面

点击左侧的 管理窗口(Management) 中 helloworld 项目下的 Sources 文件夹, 会出现 main.cpp 文件.

然后双击 main.cpp 文件, 它的内容将会出现在编辑区.

编译并运行程序

点击工具栏中的 按钮, 或者按快捷键 Ctrl+F9

也可以从菜单栏找到.

编译后, 在 Logs & Others 中可以看到编译的信息.

点击工具栏中的 按钮运行程序, 或者按快捷键 Ctrl+F10

CodeBlocks 的一些窗口

CodeBlocks 的一些窗口

Management 窗口

如果不小心关闭了 Management 窗口, 可以从菜单栏 View 中找到

或者按 Shift+F2, 它可以用来切换显示或不显示 Management 窗口. 同理, F2 可以用来切换显示或不显示 Logs 窗口.

Symbols

Files

Resources

状态栏


求 1 到 1亿中素数的个数

求 1 到 1亿中素数的个数

这里判断素数采用蛮做的办法.

//==================================
// f0618.cpp
// 求 1 ~ 100,000,000 之内的素数个数
//==================================
#include <iostream>
#include <cmath>
using namespace std;

bool isPrime(int n){
    int sqrtn=sqrt(n*1.0);
    for(int i=2;i<=sqrtn;++i)
        if(n%i==0) return false;
    return true;
}

int main()
{
    int num=0;
    int N=100000000;
    for(int i=2;i<=N;++i)
        if(isPrime(i))num++;
    cout << "小于等于 " << N << " 的素数个数有 " << num << " 个." << endl;
    return 0;
}

试一下这个程序运行的时间, 大概要几十分钟,效率太低。

原因在于判断素数的工作没有积累, 对每个自然数, 其测试都是从头做起, 哪怕单测一个整数是否是素数的效率再高, 对于大量数据测试的工作, 其算法仍显得有些笨拙.

埃拉托色尼筛法

埃拉托色尼筛法

//==================================
// f0619.cpp
// 求 1 ~ 100,000,000 之内的素数个数
// 使用埃拉托色尼筛法(The Sieve of Eratosthenes)
// 这里用到了 bitset
//==================================
#include <iostream>
#include <bitset>
using namespace std;

int main()
{
    bitset<100000000>* p=new bitset<100000000>;
    p->set();//将位集容器中所有元素置为 1.
    //p->reset(); 是将位集容器中所有元素置为 0.
    //p->test(i); 是取出第 i 个元素的值.
    int M=10000;
    int N=100000000;
    for(int i=2;i<=M;++i)
    {
        if(p->test(i))
            for(unsigned int j=i*i;j<p->size();j+=i)
                p->reset(j);
    }
    int num=0;
    for(int i=2;i < N;++i)
    {
        if(p->test(i))
            num++;
    }
    cout << "小于等于 " << N << " 的素数个数有 " << num << " 个." << endl;
    return 0;
}

筛法的低级编程

筛法的低级编程

//==================================
// f0621.cpp
// 求 1 ~ 100,000,000 之内的素数个数
// 使用埃拉托色尼筛法(The Sieve of Eratosthenes)
// 低级编程
//==================================
#include <stdio.h>
#include <stdlib.h>
#include <time.h>
using namespace std;

int count(unsigned int a){
    int sum=0;
    for(unsigned int x=a;x;x>>=1)
        if(x & 1) sum++;
    return sum;
}

void sieve(unsigned int * p){
    for(int i=2; i<=10000; ++i)
    {
        if(p[i/32]&(1 << i%32)){
            for(int j=i*i;j < 100000000;j+=i)
                p[j/32] &= ~(1 << j%32);
        }
    }
}

int main()
{
    clock_t start=clock();
    unsigned int* p =(unsigned int*)malloc(12500000);
    if(!p){
        printf("no enough memory.\n");
        return 1;
    }
    memset(p,255,12500000);
    sieve(p);
    int num=-2;
    for(int i=0;i < 12500000/4;++i)
        num+=count(p[i]);
    free(p);
    printf("%d, %7.3f\n",num,(clock()-start)/CLK_TCK);
    return 0;
}

大数加

大数加

如果我们要对两个超过 32 位以上的整数(大于 $2^{32}=4294967296$)进行加、减、乘的运算, 则需要特殊的操作.

假设 $x$ 是以 $b$ 为底的整数, $b > 2$, 则 $x$ 可以表示为

\[ x=x_0+x_1 b+x_2 b^2+\cdots+x_{n-1}b^{n-1}+x_n b^n. \]

此时我们通常简记为 $x=\overline{x_n\cdots x_0}$.


$x=\overline{x_n\cdots x_0}$, $y=\overline{y_n\cdots y_0}$, 令 $z=x+y$.

\[ \begin{split} z=&(x_0+y_0)+(x_1+y_1)b+(x_2+y_2)b^2+\cdots\\ &+(x_{n-1}+y_{n-1})b^{n-1}+(x_n+y_n)b^n. \end{split}\tag{2} \]

注意当 $x_0+y_0\geq b$ 不是一个数字, 此时要除以 $b$ 计算余数 $z_0$.

\[ x_0+y_0=\rho_1 b+z_0,\quad 0\leq z_0 < b\tag{3} \]

$\rho_1$ 被称为第一个进位(carry).

于是 \[ z=z_0+(x_1+y_1+\rho_1)b+(x_2+y_2)b^2+\cdots+(x_n+y_n)b^n.\tag{4} \]

$x_1+y_1+\rho_1$ 除以 $b$, 得到的商记为 $\rho_2$(它是第二个进位), 余数记为 $z_1$.

\[ x_1+y_1+\rho_1=\rho_2 b+z_1.\tag{5} \]

将 (5) 代入 (4), 得

\[ z=z_0+z_1 b+(x_2+y_2+\rho_2)b^2+\cdots+(x_n+y_n)b^n. \]

依次进行下去, 最终得到 \[ z=z_0+z_1 b+z_2 b^2+\cdots z_n b^n+\rho_{n+1}b^{n+1},\quad 0\leq z_i < b. \]

注意:


算法

这里进位 $\rho$ 用变量 rho 表示

rho:=0;
for i:=0 to n do begin
	temp:=x_i+y_i+rho;
	z_i:=temp mod b;
	if temp < b then rho:=0 else rho:=1
end;
if rho > 0 then overflow

void add(string & x, const string & y)
{
	int rho=0;//进位
	for(int i=0,j=y.length()-1; j>=0||rho; ++i,--j)
	{
		rho +=x[i]-'0'+(j>=0?y[j]-'0':0);
		a[i]=rho%10+'0';
		rho /=10;
	}
}






End






Thanks very much!