zoukankan      html  css  js  c++  java
  • 回避复杂—《狂人C》习题解答(第3章题7)

    题目:
          5个小孩围成一圈分糖果。最初第一个小孩有66块糖果,第二个有35块,第三个有24块,第四个有7块,第五个有34块。第一个小孩把自己的一半分给第二个小孩,然后第二个小孩把自己现有的一半分给第三个小孩……最后第五个小孩把自己现有的一半分给第一个小孩。编程模拟这个过程,输出最后每个小孩的糖果数。(每个孩子的糖果数始终为整数)

          由于在计算过程中需要记住每个小孩的糖果数目,所以使用变量存储。这些变量都有初值,因此可在定义这些变量时直接给这些变量赋初值。

    #include <stdio.h>
    #include <stdlib.h>
    
    #define PORTION 2
    
    int main( void )
    {
      int num_1 = 66 ,
          num_2 = 35 ,
          num_3 = 24 ,
          num_4 =  7 ,
          num_5 = 34 ;
    
      system("PAUSE"); 
      return 0;
    }
    

        然后逐步模拟分配的过程。首先是“第一个小孩把自己的一半分给第二个小孩”

    #include <stdio.h>
    #include <stdlib.h>
    
    #define PORTION 2
    
    int main( void )
    {
      int num_1 = 66 ,
          num_2 = 35 ,
          num_3 = 24 ,
          num_4 =  7 ,
          num_5 = 34 ;
    
      //第一个小孩把自己的一半分给第二个小孩
      num_2 += num_1 / PORTION ;
      num_1 /= PORTION ; 
    
      system("PAUSE"); 
      return 0;
    }
    

          如果写出这样的代码,逻辑上是有问题的。因为第二条语句本应该写成“num_1 -= num_1 / PORTION ;”(num_1 - num_1 / 2 =>  num_1 ),尽管其结果与“num_1 /= PORTION;”( num_1 / 2 =>  num_1 )相同,但“num_1 /= PORTION”实际上是编程者代替程序对“num_1 -= num_1 / PORTION”(num_1 - num_1 / 2 =>  num_1 )进行了进一步的演算和简化得到的。一般情况下,编程者应该把计算交给程序而不应该越俎代庖。如果题目改成了“第一个小孩把自己的三分之一分给第二个小孩”就会发现“num_1 -= num_1 / PORTION”(num_1 - num_1 / 3 =>  num_1 )依然正确,而“num_1 /= PORTION”( num_1 / 3 =>  num_1 )则是错误的。
          但是

      num_2 += num_1 / PORTION ;
      num_1 -= num_1 / PORTION ; 
    

          对次序有严格的要求,必须先执行第一句,再执行第二句。这就要求编程者在编程时付出更多的思考和谨慎,这也意味着出错的可能性更大些。如果一个写法比另一个写法更不容易出错,在两者都正确的前提下,显然第一种写法更好。学习编程只学习把代码写正确是远远不够的,更高的境界是学习写简单轻松的代码,不容易出错的代码。一定要学会回避复杂。把代码写得复杂以至于没有明显的错误固然不太容易,但编程更高的境界是,把代码写得非常简单以至于明显没有错误。
          在本题目中,这种简单轻松和不易出错体应现在:摆脱或减少对次序的强依赖,避免复杂的表达式。这可以通过增加一个临时变量实现。

    {
      int num_to_send ;
      num_to_send = num_1 / PORTION ;
      num_1 -= num_to_send ; 
      num_2 += num_to_send ;
    }
    

        这个写法后面两条语句不存在对次序的依赖,避免了“num_2 += num_1 / PORTION”这样的复杂的表达式,更直接、更简洁,因而是更好的写法。
        临时变量,有时也叫中间变量,通常用于存储计算过程中的中间计算结果。恰当地使用中间变量可以达到简化表达式,提高可读性的效果。
        下面是该问题解答的完整代码。

    #include <stdio.h>
    #include <stdlib.h>
    
    #define PORTION 2
    
    int main( void )
    {
      int num_1 = 66 ,
          num_2 = 35 ,
          num_3 = 24 ,
          num_4 =  7 ,
          num_5 = 34 ;
          
      //第一个小孩把自己的一半分给第二个小孩
       {
         int num_to_send ;
         num_to_send = num_1 / PORTION ;
         num_1 -= num_to_send ; 
         num_2 += num_to_send ;
       }
       
      //第二个小孩把自己现有的一半分给第三个小孩
       {
         int num_to_send ;
         num_to_send = num_2 / PORTION ;
         num_2 -= num_to_send ; 
         num_3 += num_to_send ;
       }
          
      //第三个小孩把自己现有的一半分给第四个小孩
       {
         int num_to_send ;
         num_to_send = num_3 / PORTION ;
         num_3 -= num_to_send ; 
         num_4 += num_to_send ;
       }
    
      //第四个小孩把自己现有的一半分给第五个小孩
       {
         int num_to_send ;
         num_to_send = num_4 / PORTION ;
         num_4 -= num_to_send ; 
         num_5 += num_to_send ;
       }
    
      //第五个小孩把自己现有的一半分给第一个小孩
       {
         int num_to_send ;
         num_to_send = num_5 / PORTION ;
         num_5 -= num_to_send ; 
         num_1 += num_to_send ;
       }
      
      printf("最后每个小孩的糖果数分别为"
             "%d,%d,%d,%d,%d\n" , 
              num_1,num_2,num_3,num_4,num_5 ) ;
    
      system("PAUSE"); 
      return 0;
    }
    
  • 相关阅读:
    Django Rest Framework --用户访问频率限制
    Django Rest Framework --权限控制
    Django Rest Framework --认证
    Django Rest Framework
    查找最大或最小的 N 个元素
    collections集合模块 [namedtuple,deque,*]
    Dream
    jQuery Ajax -附示例
    原生Ajax
    Python3 里面的线程池
  • 原文地址:https://www.cnblogs.com/KBTiller/p/2206960.html
Copyright © 2011-2022 走看看