素数判断

版本1

素数,即除1以外,只能被1和其本身整除的数。因此根据定义,最初的判断素数的方法为版本1。

//judge prime

//program 1

bool prime_1(int n)

{

int i;

for(i=2;i

{

if(n%i==0)

{

return false;

}

}

return true;

}

版本2

由于一个数的因式分解可表示为x = a * b, a<=b,因此在判断整数n是不是素数时并不需要整数从2 ~ n,只需要整除2 ~ sqrt(n) 即可。

//judge prime

//program 2

bool prime_2(int n)

{

int i,n2;

n2=sqrt(n);

for(i=2;i<=n2;i++)

{

if(n%i==0)

{

return false;

}

}

return true;

}

但是需要注意的是,int类型只能表示2^-31 ~ 2^31 范围,并不能完整表示10位大小的整数n,因此需要使用能够long long int类型。其次,求平方根的函数原型为double sqrt(double),进行sqrt(n)计算时并不确定能保证其精度。最后,对e小数点后,每个10位数字大小的整数n进行判断,需要对每个2 ~ sqrt(n)的整数进行判断,单个判断耗时间太久,所有判断重复运算太多。因此次方法必然不行。

版本3

任何一个合数都可以表现为适当个素数的乘积的形式,所以我们只用素数去除要判断的数即可,比如要判断100以内的素数,只用10以内的2,3,5,7就够了。那么首先就要构建一个素数表,以空间换时间。

可以使用一种被称为“埃拉托色尼筛”的算法。该算法一开始初始化一个2~n的连续整数序列。从2开始,2的倍数肯定不是素数,去除,剩下的数中下一个是3。再把3的倍数去除,再下一个是5(4已经去除了),以此类推,最后剩下的数必然是素数,因为它没有被筛,不是任何一个数的倍数(除了1和自己)。这样只需要很多次加法就可以了。

//create prime less then n

//program 3

#include

#include

#include //Linux, gcc -lm

#include

#define Long64 long long

#define MAX_N 8000000

Long64 prime_table[MAX_N/2]={0};

void create_prime_table(Long64 n)

{

Long64 i,j,n2;

bool prime[MAX_N+1]={0};

n2=sqrt(n);

i=2;

for(i=2;i<=n2;i++)

{

if(prime[i]==0)

{

for(j=i+i;j<=n;j+=i)

{

prime[j]=1;

}

}

}

j=0;

for(i=2;i<=n;i++)

{

if(prime[i]==0)

{

prime_table[j]=i;

j++;

printf("%lld : %lld\n",j,i);

}

}

}

void main()

{

create_prime_table(MAX_N);

}

这算是基本的筛法了,但它还有很多优化的空间。首先内存中存的表不只是素数,还有合数的空间,合数比素数多得多。 其次对于合数可能会被筛选多次,比如6,在2的时候筛掉一次。在3的时候又筛掉一次。

版本4

采用线性筛选方式,即对一个合数,只进行一次筛选,极大程度的减少重复计算。 同时,采用堆结构存放素数表。

//create prime less then n

//program 4

#include

#include

#include //Linux, gcc -lm

#include

#define Long64 long long

#define MAX_N 1000000000

void create_prime_table2(Long64 n)

{

Long64 i,j,k;

bool *prime;

Long64 *prime_table;

prime=(bool *)calloc(MAX_N+1,sizeof(bool));

prime_table=(Long64 *)calloc(MAX_N/100,sizeof(Long64));

i=2;

k=0;

for(i=2;i<=n;i++)

{

if(prime[i]==0)

{

prime_table[k++]=i;

//printf("%lld : %lld \n",k,i);

}

for(j=0;j

{

prime[prime_table[j]*i]=1;

if(i%prime_table[j]==0)

break;

}

}

printf("k = %lld\n",k);

if(prime_table)

free(prime_table);

if(prime)

free(prime);

}

void main()

{

create_prime_table2(MAX_N);

}

这样做之后,程序运行速度快多了,但是只能计算到1x10^9....再大时,运行就提示段错误了。还要再在其他地方想办法。。。 暂时先记录到这里。

自然数e

在上上一篇博客中,虽然实现了计算n为自然数e的程序,但是GetLength 函数实现的数学原理一直没有想清楚。其实是这样的。 计算自然数e时,我们使用的时泰勒公式

e^x = 1 + x + x^2/2! +... + x^n/n!...

当考虑到泰勒公式的余项时,余项可以表示为

R(x) = (e^esp * x^(n+1))/(n+1)!

其中esp在0~x之间。再取x=1,得到

R(1) = e^esp/(n+1)! <= e/(n+1)! < 10^(-M)

10^(-M)就是我们要达到的误差限,也就是小数点后的后M位。 因此,若要计算到10000位的精度,只需计算(n+1)!/e > 10^10000即可。 程序中GetLength的实现原理就是这样。

素数判断

在上一篇博客中,只计算到1x10^9内的素数,并没有达到要求,主要时卡在了数据结构上,再大的话在我2G内存32位系统上就已经提示段错误了。现在回过头了想想,其实还可以在算法上再改进。 我们知道a*b = c,一个M位的数乘上另外一个M位的数,得到结果位数范围在M+1~2M的范围内。我们只要求出5位数以内的素数,就可以用来判断10位数的整数是否为素数了。 那么素数判断的程序就可以修改成这样,也就是版本2和版本4的结合。

版本5

#include

#include

#include //Linux, gcc -lm

#include

#define Long64 long long

#define MAX_N 100000

//create prime less then n

//program 5

Long64 create_prime_table3(bool *prime, Long64 *prime_table, Long64 n)

{

Long64 i,j,k;

i=2;

k=0;

for(i=2;i<=n;i++)

{

if(prime[i]==0)

{

prime_table[k++]=i;

//printf("%lld : %lld \n",k,i);

}

for(j=0;j

{

prime[prime_table[j]*i]=1;

if(i%prime_table[j]==0)

break;

}

}

return k;

}

bool prime3(Long64 prime_table[], Long64 length, Long64 n)

{

Long64 i;

for(i=0;i

{

if(n%(prime_table[i])==0)

{

return false;

}

}

return true;

}

void main()

{

bool *prime;

Long64 *prime_table,i=0,j=0,length=0;

prime=(bool *)calloc(MAX_N+1,sizeof(bool));

prime_table=(Long64 *)calloc(MAX_N,sizeof(Long64));

length = create_prime_table3(prime,prime_table,MAX_N);

for(i=1000000000; i<10000000000; i++)

if(prime3(prime_table,length,i)!=false)

printf("%lld : %lld\n",j++,i);

}

收尾:判断e中首个连续10位素数

有了以上问题解决后,这道题终于可以解决了。不仅可以找到第一个10位长度的素数,还可以找到前10个!前10个结果如下,格式为“第几个:在e中的起始位置:要找的素数”

1:99:7427466391

2:123:7413596629

3:149:6059563073

4:171:3490763233

5:182:2988075319

6:201:1573834187

7:214:7021540891

8:218:5408914993

9:254:6480016847

10:295:9920695517

完整实现代码如下

#include

#include

#include //Linux, gcc -lm

#include

#include

#define MAX_E_BITE_N 1000

#define PRIME_N 1000000

#define Long64 long long

typedef unsigned int UINT;

int get_length(int nbite)

{

int m = 1;

double x = 2.0/2.72;

while(nbite)

{

while(x<1.0)

{

m++;

x *= (double)(m+1);

}

while(x >= 1.0 && nbite)

{

x /= 10.0;

--nbite;

}

}

while(x < 1.0)

{

m++;

x *= (double)(m+1);

}

return m;

}

int create_e(Long64 *euler, const UINT base, int m)

{

UINT *r = NULL;

UINT y = 0;

int i = 0,j = 0,k = 0;

r=(UINT *)calloc(m+1,sizeof(UINT));

assert(r != NULL);

assert(euler != NULL);

for(i = 0;i <= m; ++i)

{

r[i] = 1;

euler[i] = 0;

}

j = 1;

euler[0] = 2;

for(k = MAX_E_BITE_N; k > 0; k -= 5)

{

y = 0;

for(i = m; i >= 2; --i)

{

y = y + r[i]*base;

r[i] = y%i;

y /= i;

}

if(k < 5)

{

euler[j++] = y%base;

}

else

{

if(y < base)

euler[j++] = y;

else

{

if(r)

free(r);

return 0;

}

}

}

if(r)

free(r);

printf("\n\nE=%lld.\n",euler[0]);

for(i = 1; i < j; i++)

{

printf("%.5lld ",euler[i]);

}

printf("\n\neulur number is ok j=%d\n",j);

return j;

}

Long64 create_prime_table(bool *prime, Long64 *prime_table, Long64 n)

{

Long64 i,j,k;

i = 2;

k = 0;

for(i = 2;i <= n;i++)

{

if(prime[i] == 0)

{

prime_table[k++] = i;

// printf("%lld : %lld \n",k,i);

}

for(j = 0; j < k && (prime_table[j]*i) <= n; j++)

{

prime[prime_table[j] * i] = 1;

if(i%prime_table[j] == 0)

break;

}

}

return k;

}

bool is_prime(Long64 prime_table[], Long64 length, Long64 n)

{

Long64 i;

for(i = 0; i < length; i++)

{

if(n%(prime_table[i]) == 0)

{

return false;

}

}

return true;

}

void main()

{

const UINT base = 100000;

int m = 0,elength = 0,j = 0,find_number = 10;

Long64 *euler = NULL;

bool *prime = NULL;

Long64 *prime_table = NULL;

Long64 i = 0,length = 0,data = 0;

Long64 ten[10] = {1,10,100,1000,10000,100000,1000000,10000000,100000000,1000000000};

m = get_length(MAX_E_BITE_N);

euler = (Long64 *)calloc(MAX_E_BITE_N,sizeof(Long64));

elength = create_e(euler,base,m);

prime = (bool *)calloc(PRIME_N+1,sizeof(bool));

prime_table = (Long64 *)calloc(PRIME_N,sizeof(Long64));

length = create_prime_table(prime,prime_table,PRIME_N);

if(prime)

free(prime);

m = 0;

for(i = 1; (i+2) < elength; i++)

{

for(j = 0; j < 5; j++)

{

data = euler[i]%ten[5-j]*ten[5+j] + euler[i+1] * ten[j] + euler[i+2]/ten[5-j];

// printf("data : %lld \n",data);

if(is_prime(prime_table,length,data) == true)

{

printf("find it! %d:%lld:%lld\n",++m,5*(i-1)+j+1,data);

if(m == find_number)

break;

}

}

if(m == find_number)

break;

}

if(euler)

free(euler);

if(prime_table)

free(prime_table);

return;

}

java 自然常数e中出现的连续的第一个10个数字组成的质数,一道google面试题--自然数e中出现的连续的第一个10个数字组成的质数...相关推荐

  1. java 自然常数e中出现的连续的第一个10个数字组成的质数_冷知识:数学常数“e”的传奇故事...

    原标题:冷知识:数学常数"e"的传奇故事 自然对数的底e是一个令人不可思议的常数,一个由 lim (1+1/n)^n 定义出的常数,居然在数学和物理中频频出现,简直可以说是无处不在 ...

  2. 一道google面试题--自然数e中出现的连续的第一个10个数字组成的质数

    博客内容移到 http://www.linuxyu.com/ 此CSDN博客将不再更新,欢迎大家访问新的网站~~ Google早几年在美国很多地铁的出站口都有大幅招聘广告,它的第一题如下了:{firs ...

  3. c# 字符串中多个连续空格转为一个空格

    #region 字符串中多个连续空格转为一个空格 /// <summary> /// 字符串中多个连续空格转为一个空格 /// </summary> /// <param ...

  4. 扑克牌中的顺子。从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的。2~10为数字本身,A为1,J为11,Q为12,K为13,而大、小王可以看成任意数字。

    面试题36:扑克牌中的顺子 1.题目描述 题目:从扑克牌中随机抽5张牌,判断是不是一个顺子,即这5张牌是不是连续的.2~10为数字本身,A为1,J为11,Q为12,K为13,而大.小王可以看成任意数字 ...

  5. julia自然常数_Julia中的Sys.KERNEL常数

    julia自然常数 Julia| 系统内核常数 (Julia | Sys.KERNEL Constant) Sys.KERNEL is a constant of the Symbol type in ...

  6. c java 内部类_java程序中能否在内部类当中再定义一个内部类?

    展开全部 我被你的想62616964757a686964616fe78988e69d8331333363386664法震撼了,哈哈.亏你想的出来...这么弄代码不好理解,Java看起来醒目,也是Jav ...

  7. java自然排序_Java中的自然排序顺序字符串比较 - 是内置的吗?

    String实现了Comparable,这就是Java中的自然顺序(使用类似的接口进行比较).您可以将字符串放在TreeSet中,也可以使用Collections或Arrays类进行排序. 但是,在您 ...

  8. java合并整形_java中2个int合并成一个long

    延续32位时代的逻辑通常只会在32位整数中取出高16位和低16位的短整数(short)或相反的合并操作,如c/c++语系中loword和hiword.现在64位的cpu普及到已是标配了,所以这种经典的 ...

  9. java nanotime 重复_Java中System.nanoTime方法能作为一个唯一字符串来使用吗

    展开全部 一般使用 UUID 类来生成唯一的字符串e68a84e8a2ad62616964757a686964616f31333361313365package test; import java.u ...

最新文章

  1. 6、SpringBoot+Mybatis整合------参数传递
  2. Android开发--Spinner控件的使用
  3. JavaScript-8(正则表达式)
  4. 社会工程学[Social Engineering]
  5. Hive的安装【完整版】
  6. 【易懂】Java源码角度分析put()与putIfAbsent()的区别——源码分析系列
  7. 迁移性好、多用途,港中文提出特征分离的无监督人类三维姿态表征
  8. 数据仓库工具箱维度建模权威指南-第一章 数据仓库、商业智能及维度建模初步
  9. 《深入浅出MFC》学习笔记
  10. PHP no input file specified 三种解决方法
  11. 2020 年,哪些行业将会遭到 5G 洗礼?
  12. win8.1搭建php环境,WIN8.1下搭建PHP5.6环境
  13. shell脚本:编辑脚本check_host.sh,自动检测主机如下信息
  14. 手机拍摄证件照可以用什么软件
  15. 去爱一个无缘无故责备你的人,你就学到了生命的艺术。
  16. 如何让你的.vue在sublime text 3 中变成彩色?
  17. Lamda C++11
  18. 物联网安全威胁与解决方案调研
  19. Android之雪花飘落效果
  20. idea使用常用基础设置

热门文章

  1. 面向初学者的 MQL4 语言系列之1——MQL4 语言入门
  2. win10动态壁纸怎么设置_教程:iPhone/Android设置动态壁纸
  3. 设计原则_KISS原则
  4. CVX用户指南之快速入门
  5. Android语音提示音的制作和播放
  6. 100囚犯问题、100囚犯问题加强版与选择公理(下)
  7. 网络流量领域公开数据集及工具库
  8. ./configure时出现PKG_PROG_PKG_CONFIG和PKG_CHECK_MODULES报错的解决方案
  9. hive的like查新_Hive高级查询操作
  10. 探测工具nmap简介及使用说明