进制的意义和算法

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
", 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,则要用ABCDEF来表示
        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;
}
原文地址:https://www.cnblogs.com/organic/p/5237085.html