//*******************************

//

//    2014年9月18日星期四,于宿舍撰写

//    作者:夏华林

//

//********************************

好久没有没有更新博客了,最近确实烦心事儿挺多,已经大三了,真的静下心来好好看看书了。

今天要说的,就是一个由IsPrime算法引发的细节问题,我这里说的细节,是我所认为的,若有不妥,望指正!

一个简单的IsPrime算法的实现如下:

 bool IsPrime(int n)
{
int i; if(n % == )return false;
for(i = ; i <= sqrt(n); i += )
{
if(n%i == )return false;
}
return true;
}

这段代码中有一些严重的错误,很明显的就是,当参数为1和2的时候,函数就会返回一个错误的答案,要解决这个问题,最简单的方法就是单独检查1和2,可以在函数的开头简单的加入:

if(n <= )return false;
if(n == )return true;

还有一个性能上的问题,IsPrime算法的本意是为了提高效率,但实际情况下,有时候却会比老的算法花的时间更长。

这种问题存在于for循环的控制行中:

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

尽管现代计算机能在相当短的时间内计算平方根,但,计算平方根还是会比执行简单的算术运算要花的时间要长。程序中,每执行一次循环,都要计算一下sqrt(n),而n在整个循环中都是不变的量,那么我们每次循环都计算一下sqrt(n)就显得不那么划算,为了避免一次次的调用sqrt()函数,可以在循环前先计算出sqrt(n),把它存入一个变量,例如:

double limit = sqrt(n);
for(i = ; i <= limit; i += )

这个简单的改变,将明显的改善了IsPrime算法的实现效率。

这个IsPrime算法还有一个很难查出的问题,发现这个逻辑错误是很难的,因为它可能在你成千上万的测试例子中都不会出现,而对于一些特殊的测试例子,这个实现可能会在一些机器上能得出正确结果,而在另一个机器上得出不正确的答案。

为了理解这个问题,我觉得自己还是有必要再补写一篇关于计算机浮点数相关的文章,但限于篇幅,这里就不详细叙述其原理了

对浮点数判断严格的相等,是一个危险的行为。假设n是49,它是7的平方,当计算机对49调用sqrt()函数时,会返回什么?在严格的数学领域,这个平方根是7,但计算机并不是在这个领域内运作的,它返回的仅仅是一个接近7的浮点数,而这个数可能是6.9999999999999999999,尽管这个数很接近7,但这个差别足以影响i<=limit的结果。如果i是7,而limit是6.999999999,则循环的最后一个周期将不会得到执行,程序永远不会检查到是否可以整除7,而7又是49唯一的质因子,这样程序会错误的将49分类素数。另一方面,如果sqrt(49)返回的是7.0或者7.0000000001,那么IsPrime算法将会得到正确的答案。因而,这个实现的正确性居然要取决于硬件是如何执行浮点数运算的,而让一个算法的正确性依赖于运行它的计算机的特性是一个严重的错误。这个问题很容易解决,如果n的平方根小于某一个界限,为了保险起见,我们总倾向于多检查一个可能的约数,多测试一个约数并不会有什么害处,仅仅是付出一个非常小的代价,就能确保算法能在不同硬件上得到正确性的执行,这样的取舍对于我们来说是相当合算的

只要简单的修改:

double limit = sqrt(n) + ;

IsPrime算法本身是一个非常简单的,但其中的细节却值得我们引起足够的重视。

一个由IsPrime算法引发的细节问题的更多相关文章

  1. 【红外DDE算法】数字细节增强算法的缘由与效果(我对FLIR文档详解)

    [红外DDE算法]数字细节增强算法的缘由与效果(我对FLIR文档详解) 1. 为什么红外系统中图像大多是14bit(甚至更高)?一个红外系统的性能经常以其探测的范围来区别,以及其对最小等效温差指标.首 ...

  2. ZeroMQ接口函数之 :zmq_z85_decode – 从一个用Z85算法生成的文本中解析出二进制密码

    ZeroMQ 官方地址 :http://api.zeromq.org/4-0:zmq_z85_decode zmq_z85_decode(3)         ØMQ Manual - ØMQ/4.1 ...

  3. 一个UUID生成算法的C语言实现 --- WIN32版本 .

    一个UUID生成算法的C语言实现——WIN32版本   cheungmine 2007-9-16   根据定义,UUID(Universally Unique IDentifier,也称GUID)在时 ...

  4. 一个简单的算法,定义一个长度为n的数组,随机顺序存储1至n的的全部正整数,不重复。

    前些天看到.net笔试习题集上的一道小题,要求将1至100内的正整数随机填充到一个长度为100的数组,求一个简单的算法. 今天有空写了一下.代码如下,注释比较详细: using System; usi ...

  5. 手动实现一个虚拟DOM算法

    发现一个好文:<深度剖析:如何实现一个 Virtual DOM 算法> 源码 文章写得非常详细,仔细看了一遍代码,加了一些注释.其实还有有一些地方看的不是很懂(毕竟我菜qaq 先码 有时间 ...

  6. 自己实现一个一致性 Hash 算法

    前言 在前文分布式理论(八)-- Consistent Hash(一致性哈希算法)中,我们讨论了一致性 hash 算法的原理,并说了,我们会自己写一个简单的算法.今天就来写一个. 普通 hash 的结 ...

  7. 一个UUID生成算法的C语言实现——WIN32版本

    源: 一个UUID生成算法的C语言实现——WIN32版本

  8. 一个基于RSA算法的Java数字签名例子

    原文地址:一个基于RSA算法的Java数字签名例子 一.前言: 网络数据安全包括数据的本身的安全性.数据的完整性(防止篡改).数据来源的不可否认性等要素.对数据采用加密算法加密可以保证数据本身的安全性 ...

  9. 能够满足这样要求的哈希算法有很多,其中比较著名并且应用广泛的一个哈希算法,那就是MurmurHash 算法。尽管这个哈希算法在 2008 年才被发明出来,但现在它已经广泛应用到 Redis、MemCache、Cassandra、HBase、Lucene 等众多著名的软件中。

    能够满足这样要求的哈希算法有很多,其中比较著名并且应用广泛的一个哈希算法,那就是MurmurHash 算法.尽管这个哈希算法在 2008 年才被发明出来,但现在它已经广泛应用到 Redis.MemCa ...

随机推荐

  1. Javascript 查找字符串中出现最多的字符和出现的次数

    <script type="text/javascript"> //查找字符串中出现最多的字符和出现的次数 var str = 'Thatwheneying its o ...

  2. C语言工具的简单辨析

  3. Eclipse常用插件推荐

    Eclipse Web Tools Platform(WTP) 地址:http://download.eclipse.org/webtools/ WTP十分强大,支持HTML, JavaScript, ...

  4. 机器学习笔记1——Introduction

    Introduction What is Machine Learning? Two definitions of Machine Learning are offered. Arthur Samue ...

  5. hdoj 1200 To and Fro

    To and Fro Time Limit: 2000/1000 MS (Java/Others)    Memory Limit: 65536/32768 K (Java/Others)Total ...

  6. ffmpeg的logo, delogo滤镜参数设置

    FFmpeg的添加logo,去logo滤镜的组合共有三种方式: 1. 只有添加logo滤镜 $ ./ffmpeg -i INPUT.FLV  \ -vf movie=/opt/logo.png[log ...

  7. Spring 4.x org.springframework.http.converter.json.MappingJacksonHttpMessageConverter ClassNotFoundException:

    Spring 4.x The first major version of Jackson is no longer supported in Spring 4. The class you want ...

  8. ElasticSearch怎样加入,检索数据

    Elasticsearch是一个分布式的文档(document)存储引擎.它能够实时存储并检索复杂数据结构--序列化的JSON文档.换言说,一旦文档被存储在Elasticsearch中,它就能够在集群 ...

  9. [Oracle] - 性能优化工具(5) - AWRSQL

    在AWR中定位到问题SQL语句后想要了解该SQL statement的详细运行计划,于是就用AWR报告中得到的SQL ID去V$SQL等几个动态性能视图中查询,但发现V$SQL或V$SQL_PLAN视 ...

  10. thinkphp连接oracle

    配置文件中: //Oracle 测试环境    'DB_TYPE'     => 'Oracle',             // 数据库类型    'DB_HOST'     => '1 ...