免费注册 查看新帖 |

Chinaunix

  平台 论坛 博客 文库
最近访问板块 发新帖
查看: 6878 | 回复: 7

这个算24点的程序的bug是? [复制链接]

论坛徽章:
0
发表于 2018-07-27 15:01 |显示全部楼层
  1. #算24点程序
  2. #use strict;use warnings;use diagnostics;
  3. use strict;
  4. my $a=9;
  5. my $b=9;
  6. my $c=4;
  7. my $d=3;
  8. #利用穷举法,列出abcd四个变量之间所有的各种排列
  9. &cacu($a,$b,$c,$d);
  10. &cacu($a,$b,$d,$c);
  11. &cacu($a,$c,$b,$d);
  12. &cacu($a,$c,$d,$b);
  13. &cacu($a,$d,$b,$c);
  14. &cacu($a,$d,$c,$b);
  15. &cacu($b,$a,$c,$d);
  16. &cacu($b,$a,$d,$c);
  17. &cacu($b,$c,$a,$d);
  18. &cacu($b,$c,$d,$a);
  19. &cacu($b,$d,$a,$c);
  20. &cacu($b,$d,$c,$a);
  21. &cacu($c,$a,$b,$d);
  22. &cacu($c,$a,$d,$b);
  23. &cacu($c,$b,$a,$d);
  24. &cacu($c,$b,$d,$a);
  25. &cacu($c,$d,$a,$b);
  26. &cacu($c,$d,$b,$a);
  27. &cacu($d,$a,$b,$c);
  28. &cacu($d,$a,$c,$b);
  29. &cacu($d,$b,$a,$c);
  30. &cacu($d,$b,$c,$a);
  31. &cacu($d,$c,$a,$b);
  32. &cacu($d,$c,$b,$a);
  33. #子函数,利用三重循环计算abcd位置不变的时候的所有可能,
  34. #四个数之间只可能有三种运算符,加括号只可能有五种可能.
  35. sub cacu
  36. {
  37.     my ($a,$b,$c,$d)=@_;
  38.     my @op=("+","-","*","/");#运算符数组
  39.     my $x;my $y;my $z;
  40.     my $str1;my $str2;my $str3;my $str4;my $str5;
  41.     foreach $x (@op)#第一个运算符
  42.     {
  43.         foreach $y (@op)#第二个运算符
  44.         {
  45.             foreach $z (@op)#第三个运算符
  46.             {
  47.                 $str1="(($a$x$b)$y$c)$z$d";
  48.                 $str2="($a$x$b)$y($c$z$d)";
  49.                 $str3="($a$x($b$y$c))$z$d";
  50.                 $str4="$a$x(($b$y$c)$z$d)";
  51.                 $str5="$a$x($b$y($c$z$d))";
  52.                 if(abs(eval($str1)-24)<0.000001){print $str1 . "=24\n";}
  53.                 if(abs(eval($str2)-24)<0.000001){print $str2 . "=24\n";}
  54.                 if(abs(eval($str3)-24)<0.000001){print $str3 . "=24\n";}
  55.                 if(abs(eval($str4)-24)<0.000001){print $str4 . "=24\n";}
  56.                 if(abs(eval($str5)-24)<0.000001){print $str5 . "=24\n";}
  57.             }
  58.         }
  59.     }
  60. }
复制代码
把第三行
use strict;

换成
use strict;use warnings;use diagnostics;

那么结果将少很多,请问这啥原因导致的,我觉得程序没bug呀

论坛徽章:
0
发表于 2018-08-03 14:43 |显示全部楼层
送你上去

论坛徽章:
11
子鼠
日期:2014-10-11 16:46:4815-16赛季CBA联赛之山东
日期:2017-11-10 14:32:142016科比退役纪念章
日期:2017-09-02 15:42:4715-16赛季CBA联赛之佛山
日期:2017-08-28 17:11:5515-16赛季CBA联赛之浙江
日期:2017-08-24 16:55:1715-16赛季CBA联赛之青岛
日期:2017-08-17 19:55:2415-16赛季CBA联赛之天津
日期:2017-06-29 10:34:4315-16赛季CBA联赛之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亚冠之萨济拖拉机
日期:2015-05-22 11:38:532016科比退役纪念章
日期:2018-03-16 10:24:05
发表于 2018-08-31 09:47 |显示全部楼层
本帖最后由 523066680 于 2018-08-31 09:53 编辑

这种写法是不严谨的,0.000001这样的精度有可能在某些极端情况下导致误判,最好是所有数字作为分数处理(有理数化)

以及在计算公式中可能出现除以0而导致的错误。

验证方法就是,把数字组合 9 9 4 3 ,换成 8 9 4 3 后没有出现错误提示。


论坛徽章:
0
发表于 2018-12-10 14:09 |显示全部楼层
523066680 发表于 2018-08-31 09:47
这种写法是不严谨的,0.000001这样的精度有可能在某些极端情况下导致误判,最好是所有数字作为分数处理(有 ...

应该没多大问题,我自己也估计到是分母零的原因,

论坛徽章:
0
发表于 2018-12-15 20:07 |显示全部楼层
本帖最后由 hztj2005 于 2018-12-17 14:42 编辑

没有问题,两种方法的结果都是48个结果。我的系统是win10,Strawberry
9+((9-4)*3)=24        
((9+9)*4)/3=24        
(9+9)*(4/3)=24        
((9+9)/3)*4=24        
(9+9)/(3/4)=24        
(9-(9/3))*4=24        
9-((4-9)*3)=24        
(9*4)-(9+3)=24        
((9*4)-9)-3=24        
((9-4)*3)+9=24        
(9*4)-(3+9)=24        
((9*4)-3)-9=24        
9+(3*(9-4))=24        
9-(3*(4-9))=24        
9+((9-4)*3)=24        
((9+9)*4)/3=24        
(9+9)*(4/3)=24        
((9+9)/3)*4=24        
(9+9)/(3/4)=24        
(9-(9/3))*4=24        
9-((4-9)*3)=24        
(9*4)-(9+3)=24        
((9*4)-9)-3=24        
((9-4)*3)+9=24        
(9*4)-(3+9)=24        
((9*4)-3)-9=24        
9+(3*(9-4))=24        
9-(3*(4-9))=24        
(4*(9+9))/3=24        
4*((9+9)/3)=24        
(4*9)-(9+3)=24        
((4*9)-9)-3=24        
4*(9-(9/3))=24        
(4*9)-(3+9)=24        
((4*9)-3)-9=24        
(4*(9+9))/3=24        
4*((9+9)/3)=24        
(4*9)-(9+3)=24        
((4*9)-9)-3=24        
4*(9-(9/3))=24        
(4*9)-(3+9)=24        
((4*9)-3)-9=24        
(4/3)*(9+9)=24        
4/(3/(9+9))=24        
(4/3)*(9+9)=24        
4/(3/(9+9))=24        
(3*(9-4))+9=24        
(3*(9-4))+9=24        

  1. #算24点程序
  2. #use strict;use warnings;use diagnostics;
  3. use strict;
  4. use Algorithm::Combinatorics qw(permutations);

  5. my @data = qw(9 9 4 3);
  6. my @all_permutations = permutations(\@data);
  7. foreach (@all_permutations){
  8.         #print join(' ', @$_), "\n";
  9.         &cacu(@$_);  
  10. }

  11. #子函数,利用三重循环计算abcd位置不变的时候的所有可能,
  12. #四个数之间只可能有三种运算符,加括号只可能有五种可能.
  13. sub cacu
  14. {
  15.     my ($a,$b,$c,$d)=@_;
  16.     #print "$a,$b,$c,$d\n";
  17.     my @op=("+","-","*","/");#运算符数组
  18.     my $x;my $y;my $z;
  19.     my $str1;my $str2;my $str3;my $str4;my $str5;
  20.     foreach $x (@op)#第一个运算符
  21.     {
  22.         foreach $y (@op)#第二个运算符
  23.         {
  24.             foreach $z (@op)#第三个运算符
  25.             {
  26.                 $str1="(($a$x$b)$y$c)$z$d";
  27.                 $str2="($a$x$b)$y($c$z$d)";
  28.                 $str3="($a$x($b$y$c))$z$d";
  29.                 $str4="$a$x(($b$y$c)$z$d)";
  30.                 $str5="$a$x($b$y($c$z$d))";
  31.                 if(abs(eval($str1)-24)<0.000001){print $str1 . "=24\n";}
  32.                 if(abs(eval($str2)-24)<0.000001){print $str2 . "=24\n";}
  33.                 if(abs(eval($str3)-24)<0.000001){print $str3 . "=24\n";}
  34.                 if(abs(eval($str4)-24)<0.000001){print $str4 . "=24\n";}
  35.                 if(abs(eval($str5)-24)<0.000001){print $str5 . "=24\n";}
  36.                 #print "$x,$y,$z\n";
  37.             }
  38.         }
  39.     }
  40. }
复制代码

论坛徽章:
0
发表于 2018-12-16 13:28 |显示全部楼层
本帖最后由 hztj2005 于 2018-12-16 13:29 编辑

上面48个结果用excel排序后,可以看出两两重复,实际只有24个结果:
35
((4*9)-3)-9=24
42
((4*9)-3)-9=24
32
((4*9)-9)-3=24
39
((4*9)-9)-3=24
12
((9*4)-3)-9=24
26
((9*4)-3)-9=24
9
((9*4)-9)-3=24
23
((9*4)-9)-3=24
2
((9+9)*4)/3=24
16
((9+9)*4)/3=24
4
((9+9)/3)*4=24
18
((9+9)/3)*4=24
10
((9-4)*3)+9=24
24
((9-4)*3)+9=24
48
(3*(9-4))+9=24
47
(3*(9-4))+9=24
29
(4*(9+9))/3=24
36
(4*(9+9))/3=24
34
(4*9)-(3+9)=24
41
(4*9)-(3+9)=24
31
(4*9)-(9+3)=24
38
(4*9)-(9+3)=24
43
(4/3)*(9+9)=24
45
(4/3)*(9+9)=24
6
(9-(9/3))*4=24
20
(9-(9/3))*4=24
11
(9*4)-(3+9)=24
25
(9*4)-(3+9)=24
8
(9*4)-(9+3)=24
22
(9*4)-(9+3)=24
3
(9+9)*(4/3)=24
17
(9+9)*(4/3)=24
5
(9+9)/(3/4)=24
19
(9+9)/(3/4)=24
30
4*((9+9)/3)=24
37
4*((9+9)/3)=24
33
4*(9-(9/3))=24
40
4*(9-(9/3))=24
44
4/(3/(9+9))=24
46
4/(3/(9+9))=24
7
9-((4-9)*3)=24
21
9-((4-9)*3)=24
14
9-(3*(4-9))=24
28
9-(3*(4-9))=24
1
9+((9-4)*3)=24
15
9+((9-4)*3)=24
13
9+(3*(9-4))=24
27
9+(3*(9-4))=24
   
   

论坛徽章:
11
子鼠
日期:2014-10-11 16:46:4815-16赛季CBA联赛之山东
日期:2017-11-10 14:32:142016科比退役纪念章
日期:2017-09-02 15:42:4715-16赛季CBA联赛之佛山
日期:2017-08-28 17:11:5515-16赛季CBA联赛之浙江
日期:2017-08-24 16:55:1715-16赛季CBA联赛之青岛
日期:2017-08-17 19:55:2415-16赛季CBA联赛之天津
日期:2017-06-29 10:34:4315-16赛季CBA联赛之四川
日期:2017-05-16 16:38:55黑曼巴
日期:2016-07-19 15:03:112015亚冠之萨济拖拉机
日期:2015-05-22 11:38:532016科比退役纪念章
日期:2018-03-16 10:24:05
发表于 2018-12-16 19:33 |显示全部楼层
本帖最后由 523066680 于 2018-12-16 21:29 编辑
我觉得程序没bug呀
&
应该没多大问题

那我就针对这个精确度给一个极端的例子吧
my ($a,$b,$c,$d)=qw/1 10000 9998 24/;

输出:
  1. (1/(10000*9998))+24=24
  2. ((1/10000)/9998)+24=24
  3. (1/(9998*10000))+24=24
  4. ((1/9998)/10000)+24=24
  5. (10000-(1+9998))*24=24
  6. ((10000-1)-9998)*24=24
  7. (10000-(9998+1))*24=24
  8. ((10000-9998)-1)*24=24
复制代码
后面几个是对的,但
(1/(10000*9998))+24=24

则是不对的

--------------------------------
另外关于报错的源头,也很好检查的
使用$@可以获取错误信息
  1. if(abs(eval($str2)-24)<0.000001){print $str2 . "=24\n";}
  2. printf "%s %s", $str2, $@ if ( $@ );
复制代码
部分输出结果
  1. (4+3)/(9-9) Illegal division by zero at (eval 5194) line 1.
  2. (4-3)/(9-9) Illegal division by zero at (eval 5274) line 1.
  3. (4*3)/(9-9) Illegal division by zero at (eval 5354) line 1.
  4. (4/3)*(9+9)=24
  5. 4/(3/(9+9))=24
  6. (4/3)/(9-9) Illegal division by zero at (eval 5434) line 1.
  7. (4+3)/(9-9) Illegal division by zero at (eval 5514) line 1.
  8. (4-3)/(9-9) Illegal division by zero at (eval 5594) line 1.
  9. (4*3)/(9-9) Illegal division by zero at (eval 5674) line 1.
  10. (4/3)*(9+9)=24
  11. 4/(3/(9+9))=24
  12. (4/3)/(9-9) Illegal division by zero at (eval 5754) line 1.
  13. (3*(9-4))+9=24
  14. (3*(9-4))+9=24
  15. (3+4)/(9-9) Illegal division by zero at (eval 7114) line 1.
  16. (3-4)/(9-9) Illegal division by zero at (eval 7194) line 1.
  17. (3*4)/(9-9) Illegal division by zero at (eval 7274) line 1.
  18. (3/4)/(9-9) Illegal division by zero at (eval 7354) line 1.
  19. (3+4)/(9-9) Illegal division by zero at (eval 7434) line 1.
  20. (3-4)/(9-9) Illegal division by zero at (eval 7514) line 1.
  21. (3*4)/(9-9) Illegal division by zero at (eval 7594) line 1.
  22. (3/4)/(9-9) Illegal division by zero at (eval 7674) line 1.
复制代码


论坛徽章:
0
发表于 2019-01-15 15:31 |显示全部楼层
回复 7# 523066680

debug的时候,可以观察$@变量,也差不多能知道是因为分母等于零的原因
您需要登录后才可以回帖 登录 | 注册

本版积分规则 发表回复

SACC2019中国系统架构师大会

【数字转型 架构演进】SACC2019中国系统架构师大会,7折限时优惠重磅来袭!
2019年10月31日~11月2日第11届中国系统架构师大会(SACC2019)将在北京隆重召开。四大主线并行的演讲模式,1个主会场、20个技术专场、超千人参与的会议规模,100+来自互联网、金融、制造业、电商等领域的嘉宾阵容,将为广大参会者提供一场最具价值的技术交流盛会。

限时七折期:2019年8月31日前


----------------------------------------

大会官网>>
  

北京盛拓优讯信息技术有限公司. 版权所有 16024965号-6 北京市公安局海淀分局网监中心备案编号:11010802020122
中国互联网协会会员  联系我们:help@itpub.net
感谢所有关心和支持过ChinaUnix的朋友们 转载本站内容请注明原作者名及出处

清除 Cookies - ChinaUnix - Archiver - WAP - TOP