數學黑洞:卡普雷卡爾常數的php算法實現


首先看一篇文章:

 

  英國廣播公司報道,6174乍看沒什么奇特之處,但是,自從1949年以來,它一直令數學家、數字控抓狂、痴迷。

  不管你挑的四位數是什么,早早晚晚你都會遇到6174;而且,遇到6174就只能止步,否則面臨的將是無休無止的無用功了。

  祝賀一下,現在你總算搞懂了卡普雷卡爾常數(Kaprekar's constant,又稱卡布列克常數)。

  印度數學家卡普雷卡爾(1905-1986)最喜歡擺弄數字,正是他發現了6174的神奇魅力。

  自認數字理論控的卡普雷卡爾1949年在印度城市馬德拉斯召開的一次數學會議上向世界宣布了自己的發現。

卡普雷卡爾就讀於孟買大學,畢業后在孟買北部山區小鎮帶奧拉利(Devlali)當老師。

  印度數學家認為,卡普雷卡爾的發現很無聊,取笑一番,置之不理。不過,卡普雷卡爾是位高產作家,經常在大眾科普刊物上發表文章。而且,他還常被請去參加各種會議、在學校巡回演說,介紹自己獨特的方法和有趣的發現。

  逐漸,卡普雷卡爾在國內外知名度、受歡迎程度越來越高。到了1970年,美國暢銷書作家、數學愛好者Martin Gardner在著名科普雜志《科學美國人》上發表文章介紹卡普雷卡爾。

  現在,卡普雷卡爾的名字在全世界數學愛好者——特別是數字控中——已經是如雷貫耳。

  日本大阪經濟大學教授西山豊(Yutaka Nishiyama)認為,6174真是個“謎一樣的數字”。在一篇網上文章中,西山教授解釋說,他用電腦查證是否所有的四位數都能在有限步驟內得出6174。

  他的發現是,根據卡普雷卡爾的算法,所有四位數(只要四位數不重復)最多只需要7步運算就會得出6174。

  “如果7步還沒有得出6174,那一定是你算錯了。重來一遍吧。”

 

  把下面的代碼保存為 index.php 存入服務器中,在瀏覽器中每刷新一次,程序會隨機取出四位數進行卡普雷卡爾常數運算十步。

  (一)面向過程實現:

<?php
/**
  *  卡普雷卡爾常數的計算(6174的數字黑洞)
  *
  * 計算方法:任意四個不重復的一位數,它們組成的最大四位數減去它們組成的
  *         最小四位數所得的新四位重復前面的算法,最多七次就會得到6174。
  */
  
// 隨機數產生四位原始數字的數組
$original = array( rand(1,9), rand(1,9), rand(1,9), rand(1,9));
$orig = implode( $original );
echo "<br>原數據:{$orig}<br>";

/**
  * $total[0]存放計算前的四位數
  * $total[1]存放計算后的四位數
  * $total[2]存放計算得到6174后的計算次數
  */
$total = array( 0, 0, 0 );
$tag = true;

/**
  * 整個計算就是一個 for 循環加 3 個函數完成的
  * 計算 10 次數據
  */
for( $i = 0; $i < 10; $i++)
{
    if( empty( $total[0] ) )
        $total[1] =$total[0] = calculation( $original );
    else
        $total[1] = calculation(  numToArr( $total[0] ) );

    // *****輸出計算后的數據*****
    echo $total[1] . '<br>';
    
    if( $total[1] == 6174 && $tag)
    {
        $tag = false;
        $total[2] = $i;
    }
    $total[0] = $total[1];
}

echo '在第<strong style="color: red">' . $total[2] . '</strong>步使數據等於6174。<br>';

/**
  * 冒泡排序算法函數
  * ( php有原生的排序函數 sort() 升序和 rsort() 降序排序 )
  *
  * @param array $arr   要排序的數組;
  * @param bool  $order 為 true 升序,為 false 降序。
  * @return array
  */
  
function sortFunc($arr, $order = true)
{
    $val = 0;
    $count = count($arr) - 1;
    
    for($i = 0; $i < $count; $i++)
    {
        for($j = 0; $j < $count - $i; $j++)
        {
            if($order)
            {
                if($arr[$j] > $arr[$j + 1])
                {
                    $tag[1]++;
                    $val = $arr[$j + 1];
                    $arr[$j + 1] = $arr[$j];
                    $arr[$j] = $val;
                }
            }
            else
            {
                if($arr[$j] < $arr[$j + 1])
                {
                    $val = $arr[$j + 1];
                    $arr[$j + 1] = $arr[$j];
                    $arr[$j] = $val;
                }
            }
        }
    }
    return $arr;
}

/**
  * 卡普雷卡爾常數的計算函數
  *
  * 功能:任意四位數,排序后的最大數減去排序后的最小數。
  * @param array $arr 輸入的任意四位數。
  * @return integer
  */
  
function calculation( $arr ){
    //①用冒泡排序法實現
    $big = sortFunc( $arr, false );
    $small = sortFunc( $arr);
    
    //②用 php 內置函數實現
    //$big = $small = $arr;
    //rsort( $big, SORT_NUMERIC );
    //sort( $small, SORT_NUMERIC );

    $valBig = ( int )implode( $big );
    $valSmall = ( int )implode( $small );

    $value = $valBig - $valSmall;
    return $value;
}

/**
  * 數字拆分成數組函數
  * 
  * @param integer $num 四位數如:8543
  * @return array       得到的數組如:array( 8, 5, 4, 3 )
* 如果用原生 php 函數是 str_split()
*/ function numToArr( $num ){ $arr = array(); $str = (string)$num; for( $i = 0; $i < strlen( $str ); $i++) { $arr[] = (int)substr( $str, $i, 1); } return $arr; }

 

  (二)用面向對象實現上面的面向過程:

<?php
/**
  *  卡普雷卡爾常數的計算(6174的數字黑洞)
  *
  * 計算方法:任意四個不重復的一位數,它們組成的最大四位數減去它們組成的
  *         最小四位數所得的新四位重復前面的算法,最多七次就會得到6174。
  */
   
class KaprekarConst{
    
    public $original = array();
    
    /**
      * $total[0]存放計算前的四位數
      * $total[1]存放計算后的四位數
      */
    public $total = array( 0, 0 );
    public $tag = true;
    
    /**
      * $val[0] 存放四位原始數據
      * $val[1] 存放循環計算 10 次的數組
      * $val[2] 存放計算到 6174 數據的次數
      */
    public $val = array();
    
    function __construct()
    {
        // 隨機數產生四位原始數字的數組
        $this->original = array( rand(1,9), rand(1,9), rand(1,9), rand(1,9));
    }
    
    public function main()
    {
        $this->val[0] = implode( $this->original );
        
        /**
          * 整個計算就是一個 for 循環加 2 個方法完成的
          * 計算 10 次數據
          */
        for( $i = 0; $i < 10; $i++)
        {
            if( empty( $this->total[0] ) )
                $this->total[1] = $this->total[0] = $this->calculation( $this->original );
            else
                $this->total[1] = $this->calculation(  $this->numToArr( $this->total[0] ) );
    
            // *****輸出計算后的數據*****
            $this->val[1][] = $this->total[1];
    
            if( $this->total[1] == 6174 && $this->tag)
            {
                $this->tag = false;
                $this->val[2] = $i;
            }
            $this->total[0] = $this->total[1];
        }
return $this->val; } /** * 卡普雷卡爾常數的計算方法 * * 功能:任意四位數,排序后的最大數減去排序后的最小數。 * @param array $arr 輸入的任意四位數。 * @return integer */ public function calculation( $arr ){ $big = $small = $arr; rsort( $big, SORT_NUMERIC ); sort( $small, SORT_NUMERIC ); $valBig = ( int )implode( $big ); $valSmall = ( int )implode( $small ); $value = $valBig - $valSmall; return $value; } /** * 數字拆分成數組方法 * * @param integer $num 四位數如:8543 * @return array 得到的數組如:array( 8, 5, 4, 3 )
* 如果用原生 php 函數是 str_split()
*/ public function numToArr( $num ){ $arr = array(); $str = (string)$num; for( $i = 0; $i < strlen( $str ); $i++) { $arr[] = (int)substr( $str, $i, 1); } return $arr; } } $obj = new KaprekarConst; $val = $obj->main(); // 顯示內容: echo '原數據:' . $val[0] . '<br>'; foreach( $val[1] as $value ) { echo $value . '<br>'; } echo '在第<strong style="color: red">' . $val[2] . '</strong>步使數據等於6174。';

 

程序執行后的效果:

 


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM