進制的意義和算法


1、問題

1.1 蘋果裝箱

小明家摘了123個蘋果,10個蘋果可以裝滿1箱,10箱蘋果就可以裝滿1車拉到批發市場去出售了,問這些蘋果一共能裝滿幾車,幾箱,還剩幾個蘋果?

聰明的朋友可能直接給出答案是1車2箱,最后剩3個蘋果。

計算的過程:

123個 / 10 = 12箱,余3個蘋果

12箱 / 10 = 1車,余2箱

當然,有朋友會立即指出,為啥要這么SB的算,123的百位1不就是1車,十位2 = 2箱,個位3 = 3個

沒錯,這就是123這個數表示的意義。百位表示車的數量,十位表示箱的數量,個位表示剩下蘋果個數。

假設我們的蘋果每滿10個就必須裝箱,每滿10箱就必須裝車賣掉(否則就爛了),而這個裝箱裝車就是我們所謂的進位。

1.2 銀行換錢

小明現在有123個1分硬幣,想去銀行換成整的,最后可換得1元2毛零3分。

這里同樣的,1元即是百位的數,2毛即是十位的數,3分就是位的數,這就是數字說代表的現實意義。

 

2、位的意義及數學概念

2.1 萬能公式

所有的十進制數都可以用一個公式來表示:

image

指數n = an所在的位數,個位n=0,十位n=1,依次遞增

an = 對應位數上的數值

10 = 十進制

那么就有一個萬能公式來描述所有進制的記數:

image

2.2 問題1.1的另一個思考

123個蘋果,如果交給計算機去計算能裝滿幾車,幾箱,還剩幾個蘋果?

這時候計算機不能用眼睛去看出123這個數字說表示的意義了,但發現用1.1的計算過程計算機可以描述出來:

a =  num % 10;           //a 依次等於個、箱、車
num = num / 10;
Loop…

同時可能有的朋友有一種想法:

車的指數n=2,貌似把num / 100 = 1 就是車的數量

但是有2個問題:

  • 計算機不知道123的數字的長度,假設我們是23個蘋果,再去除100就是得到的商是0,0一般是自動忽略的,故此步是多余計算的
  • 如果要求箱的數量,num / 10 = 12,這就不對了

如果求余數也會有類似的問題,但求最后剩下的蘋果個數時,余數總是對的:

123 % 10 = 3 個

所以才有每次除10的操作,依次讓箱、車的位變為個位,也就是編程中的右移操作,然后再求余就沒什么問題了,這時候我們多想,要是10進制也有位移操作符多好啊

2.3 10進制的移位操作

當我們把 num 除 10時(余數丟棄,不處理小數),會有一個神奇的現象:

123 / 10 = 12

12 / 10 = 1

這實際上已經是在進行右移操作了,所以10進制右移即是將其除10(左移即是將其乘10),而其余數即是被移除的最低位的數值

2.4 數學證明(注意不涉及小數計算,余數丟棄)

image

此時a1變為個位了,下次再繼續除10,就會將a1移出了

於是,我們就能利用該方法不斷的將數右移,然后移出的余數就是對應位上的數的值了。

 

3、應用

上面說了一堆公式和理論,沒看出有啥實際的用處,而理論是為了實踐服務的,那么下面就讓我們來看看它如何干活的吧

3.1 計算問題1.1中的蘋果裝箱問題

void    CTestMath::LoadApple(unsigned uNum)
{
    int            nSize = 0;
    unsigned    uAppleArray[3] = {0};

    while (uNum)
    {
        uAppleArray[nSize] = uNum % 10;
        uNum /= 10;
        nSize++;
    }

    printf("The apples can load to %d car, %d box, left %d apple\n", uAppleArray[2], uAppleArray[1], uAppleArray[0]);
}

3.2 將一個num以10進制形式的字符輸出(和蘋果裝箱問題類似)

int    CTestMath::OutputDecimalNum(unsigned uNum, char* pszNum)
{
    int    nSize = 0;

    while (uNum)
    {
        pszNum[nSize] = (uNum % 10) + '0';
        uNum /= 10;
        nSize++;
    }

    //因為是從低位開始處理,所以放入pszNum的數是倒置的,需要對調一下
    for (int i = 0; i < nSize / 2; i++)
    {
        char    cTemp = pszNum[i];
        pszNum[i] = pszNum[nSize - 1 - i];
        pszNum[nSize - 1 - i] = cTemp;
    }

    pszNum[nSize] = NULL;
    return    nSize - 1;
}

 

4 16進制

4.1 回到問題1.1,隨着小明賣蘋果有錢了,新換了一輛大車,能裝16箱蘋果,同時增大了箱子,每箱能裝16個蘋果,此時123個蘋果能裝能裝滿幾車,幾箱,還剩幾個蘋果?

image

此時我們發現,從123的字面上不能直接給出答案了,怎么辦?

采用1.1中類似的計算方法:

123個 / 16 = 7箱,余11個蘋果,用16進制記為B

7箱 / 16 = 0箱,余7箱

所以答案是能裝滿0車,7箱,剩B(11)個蘋果,記為數字"7B"

此時我們再來看"7B"這個數,就可以用1.1中的方法看出,十位"7"即為箱數,個位B即為剩余的蘋果數,可以預計,百位即為車數,這就是不同進制的數的實際意義。

實際上,在我們的實際生活中,我們也有其他進制的應用,如時鍾,秒到分,分到小時,即是60進制的,如要問123456秒等於多少小時,多少分,多少秒?即可用類似的算法解決。

4.2 數學證明

回到我們的萬能公式,將其轉化為16進制的形式:

image

此公式依然成立,所以我們能用同樣的方法解決16進制中的問題

4.2 將10進制數轉化為16進制數形式字符

int    CTestMath::DecimaltoHexadecimal(unsigned uNum, char* pszHexNum)
{
    int        nSize = 0;
    char    cTemp = 0;

    while (uNum)
    {
        cTemp = (uNum % 16);

        //如果數值大於9,則要用A\B\C\D\E\F來表示
        if (cTemp > 9)
        {
            cTemp += ('A' - 10);
        }
        else
        {
            cTemp += '0';
        }

        pszHexNum[nSize] = cTemp;
        uNum /= 16;
        nSize++;
    }

    //因為是從低位開始處理,所以放入pszNum的數是倒置的,需要對調一下
    for (int i = 0; i < nSize / 2; i++)
    {
        cTemp = pszHexNum[i];
        pszHexNum[i] = pszHexNum[nSize - 1 - i];
        pszHexNum[nSize - 1 - i] = cTemp;
    }

    pszHexNum[nSize] = NULL;
    return    nSize - 1;
}


免責聲明!

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



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