发现错误
来源:广州中睿信息技术有限公司官网
发布时间:2012/10/21 23:25:16 编辑:editor 阅读 354
今天无意在一个朋友的Blog上看见有Duff&rsquosDevice循环算法(原理Baidu或Google有详细介绍)的文章,点进去看了看,发现问题多多。代码//credit:JeffGreenb

今天无意在一个朋友的Blog上看见有Duff’s Device循环算法(原理BaiduGoogle有详细介绍)的文章,点进去看了看,发现问题多多。

代码

  //credit: Jeff Greenberg  var iterations = Math.floor(items.length / 8),       startAt = Items.length % 8,       i = 0;  do{    switch(startAt){      case 0: process(items[i++]);      case 7: process(items[i++]);      case 6: process(items[i++]);      case 5: process(items[i++]);      case 4: process(items[i++]);      case 3: process(items[i++]);      case 2: process(items[i++]);      case 1: process(items[i++]);    }  }while(--iterations);

 和优化后的版本

  //credit: Jeff Greenberg  var i = items.length % 8;  while(i){    process(items[i--]);  }  i = Math.floor(items.length / 8);  while(i){    process(items[i--]);    process(items[i--]);    process(items[i--]);    process(items[i--]);    process(items[i--]);    process(items[i--]);    process(items[i--]);    process(items[i--]);  }

  看了一下,错误颇多,也可能也是网上转帖,没有仔细研究过此算法的原理。

一版代码

1,将swtich引入到了do中增加了每次循环的性能开销,原版算法中使用switch+case+do其实是利用了C语言的编译机制的"跌落"行为,实现了switch只会在首次运行起效的功能.

2,startAt未置0 -> 此处变量只是用于计算出首次运行批次执行操作次数,只能第一批次有效,运行完之后应该置为0,保证此后每批次运行8次。

3,iterations 计算错误 ->  Math.floor是返回小于等于数字参数的最大整数,对数字进行下舍入,在while循环中边界检测时会导致最终循环批次会少一次。

4,边界值检测不严谨 , 当iterations = 0 时,会陷入死循环

5,未考虑空序列

 

二版代码

1,利用了while循环进行首批次运行,其实是增加了一轮n > 0 的边界值检测,虽然至多增加8次的比对,性能也差不多,但失去了原版算法的原意。

2,i的两次赋值. 第一次赋值可以认为是算出执行不满8位的批次的操作数,第二次赋值可以认为是剩余项的执行批次.但是执行取item数组索引时,使用i--,这个完全是错误操作,把批次和当前项索引搞错了。直接导致报错

 

贴一段我整合修改后的版本

 

   1 function doSth(num) {   2             console.log(num);   3  }   4    5    6         //new version   7         function ForEachExtend(items, process) {   8             if (items.length > 0) {   9                 var startAt = items.length % 8, i = 0, iterations = Math.ceil(items.length / 8);  10   11                 switch (startAt) {  12                     case 0: process(items[i++]);  13                     case 7: process(items[i++]);  14                     case 6: process(items[i++]);  15                     case 5: process(items[i++]);  16                     case 4: process(items[i++]);  17                     case 3: process(items[i++]);  18                     case 2: process(items[i++]);  19                     case 1: process(items[i++]);  20                 }  21   22                 while (--iterations > 0) {  23                     process(items[i++]);  24                     process(items[i++]);  25                     process(items[i++]);  26                     process(items[i++]);  27                     process(items[i++]);  28                     process(items[i++]);  29                     process(items[i++]);  30                     process(items[i++]);  31                 }  32             }  33         }  34   35         console.log("空数组===>");  36         ForEachExtend([], doSth);  37         console.log("长度为1数组===>");  38         ForEachExtend([1], doSth);  39         console.log("长度可被整除数组===>");  40         ForEachExtend([1, 2, 3, 4, 5, 6, 7, 8], doSth);  41         console.log("长度>8数组===>");  42         ForEachExtend([1, 2, 3, 4, 5, 6, 7, 8, 9], doSth);

 

 

上网查询了一下网络相关的javascript实现,发现基本都是千篇一律,不管是AS还是Javascript实现都或多或少存在我上面发现的问题,代码基本都是雷同,这些问题都是通过一定的代码阅读都能发现的,结果基本都是顺手粘贴,也不考究测试一下是否可行,真是天下文章一大抄,送到嘴边的肉都不嚼一下就咽下去了。

另在网络上的JavaScript高性能编程这本书上也发现是这么写,让我很是意外。这个问题难道是我搞错了?很是奇怪.

 

联系我们CONTACT 扫一扫
愿景:成为最专业的软件研发服务领航者
中睿信息技术有限公司 广州•深圳 Tel:020-38931912 务实 Pragmatic
广州:广州市天河区翰景路1号金星大厦18层中睿信息 Fax:020-38931912 专业 Professional
深圳:深圳市福田区车公庙有色金属大厦509~510 Tel:0755-25855012 诚信 Integrity
所有权声明:PMI, PMP, Project Management Professional, PMI-ACP, PMI-PBA和PMBOK是项目管理协会(Project Management Institute, Inc.)的注册标志。
版权所有:广州中睿信息技术有限公司 粤ICP备13082838号-2