非负整数十进制与二进制之间的转换

  本文将简单的讨论非负整数的N进制与十进制之间如何进行转换。

一、十进制与二进制的表示

  先来看十进制数的表示,数n的十进制可以分解为n = d[0] + d[1] * 10 + d2 * 10^2 + …… + d[k] * 10^k,其中0 <= d[i] < 10,例如12345 = 5 + 4 * 10 + 3 * 10^2 + 2 * 10^3 + 1 * 10^4,也就是d[0] = 5, d[1] = 4, d[2] = 3, d[3] = 2, d[4] = 1,数n的十进制表示为d[k]d[k-1]……d[1]d[0],对于上述例子即12345

  同样地,数m的二进制可以表示为m = b[0] + b[1] * 2^1 + …… + b[k] * 2^k,其中0 <= b[i] < 2,例如7 = 1 + 1 * 2^1 + 1 * 2^2,也就是b[0] = 1, b[1] = 1, b[2] = 1,数m的二进制表示为b[k]b[k-1]……b[1]b[0],对于上述例子即111

二、十进制转换成二进制

  思考一下,对于一个数,我们是如何求它十进制对应的每一位?例如n = 9527,我们通过n % 10求得个位上的数是9527 % 10 = 7,然后令n = n / 10(取整除部分),重复n % 10n = n / 10这个过程即可得到十位、百位、千位的数字分别为257。把每一位合起来就是该数的十进制表示。

  同样的,对于一个数,我们可以通过上述方法求它二进制对应的每一位。假设对于数字m,通过m % 2即可求得它的个位,然后令m = m / 2,继续上述过程即可求得十位、百位、……等等。举个例子来说m = 11,那么个位为m % 2 = 1,令m = m / 2 = 11 / 2 = 5,那么十位为m % 2 = 5 % 2 = 1,即十位为1,继续令m = m / 2 = 5 / 2 = 2,那么百位为m % 2 = 2 % 2 = 0,即百位为0,继续令m = m / 2 = 2 / 2 = 1,那么千位为m % 2 = 1 % 2 = 1,即千位为1,此时m = m / 2 = 1 / 2 = 0,到此转换结束,因此最终的二进制表示为1011

  C++示例代码如下:


// Conver.h
#include <string>
namespace Convert {
    std::string DecimalToBinary(unsigned int d);
};
// Conver.cpp
#include <string>
namespace Convert {
    std::string DecimalToBinary(unsigned int d)
    {
        if (d == 0) {
            return "0";
        }

        std::string result;
        while (d > 0) {
            result += ('0' + d % 2);
            d /= 2;
        }

        std::reverse(result.begin(), result.end());
        return result;
    }

};
// test.cpp
#include <iostream>
#include "Convert.h"
int main(int argc, char **argv)
{
    std::cout << "0 to binary is: " << Convert::DecimalToBinary(0) << std::endl;
    std::cout << "1 to binary is: " << Convert::DecimalToBinary(1) << std::endl;
    std::cout << "2 to binary is: " << Convert::DecimalToBinary(2) << std::endl;
    std::cout << "10 to binary is: " << Convert::DecimalToBinary(10) << std::endl;
    std::cout << "16 to binary is: " << Convert::DecimalToBinary(16) << std::endl;
    std::cout << "9527 to binary is: " << Convert::DecimalToBinary(9527) << std::endl;
    return 0;
}
// 执行结果
0 to binary is: 0
1 to binary is: 1
2 to binary is: 10
10 to binary is: 1010
16 to binary is: 10000
9527 to binary is: 10010100110111

三、二进制转换为十进制

  思考一下,对于十进制表示的数n = d[3]d[2]d[1]d[0],我们如何求得它的结果?很显然是:(((d[3] * 10) + d[2]) * 10 + d[1]) * 10) + d[0]。那么对于二进制表示的数m = b[3]b[2]b[1]b[0],同样可得到它的结果为(((b[3] * 10) + b[2]) * 10 + b[1]) * 10) + b[0]。因为在我们当前的运算体系中,都是以十进制来表示的,所以对于(((d[3] * 10) + d[2]) * 10 + d[1]) * 10) + d[0](((b[3] * 10) + b[2]) * 10 + b[1]) * 10) + b[0]得到的都是以十进制表示的结果。那么对于二进制转换为十进制,C++代码如下:


// Conver.h
#include <string>
namespace Convert {
    unsigned int BinaryToDecimal(const std::string &b);
};
// Conver.cpp
#include <string>
namespace Convert {
    unsigned int BinaryToDecimal(const std::string &b)
    {
        if (b.size() == 0) {
            return 0;
        }

        unsigned int result = 0;
        for (const auto &c : b) {
            result = result * 2 + (c - '0');
        }

        return result;
    }
};
// test.cpp
#include <iostream>
#include "Convert.h"
int main(int argc, char **argv)
{
    std::cout << "null to decimal is: " << Convert::BinaryToDecimal("") << std::endl;
    std::cout << "0 to decimal is: " << Convert::BinaryToDecimal("0") << std::endl;
    std::cout << "1 to decimal is: " << Convert::BinaryToDecimal("1") << std::endl;
    std::cout << "10 to decimal is: " << Convert::BinaryToDecimal("10") << std::endl;
    std::cout << "1000 to decimal is: " << Convert::BinaryToDecimal("1000") << std::endl;
    std::cout << "1100101 to decimal is: " << Convert::BinaryToDecimal("1100101") << std::endl;
    return 0;
}
// 执行结果
null to decimal is: 0
0 to decimal is: 0
1 to decimal is: 1
10 to decimal is: 2
1000 to decimal is: 8
1100101 to decimal is: 101

四、数的任意进制表示

  在前面的描述中,是把数的进制表示做了区分的。更像是一个客观存在的概念,而数的进制表示则只是这个某个进制上的外在表现形式,不管是以何种进制来表示这个数,数的大小都是客观不变且一致的。

  那么对于一个数mN进制我们该如何表示?按照本文的第一节,我们可以写成m = d[0] + d[1] * N^1 + d[2] * N^2 + …… + d[k] * N^k;因此,d[k][d[k-1]……d[1]d[0]即为数mN进制表示(注意要满足0 <= d[i] < N)。

  • 将十进制转换成N进制数。我们可以通过如下两步来得到数mN进制表示:
  1. 初始时i = 0
  2. d[i] = m % N
  3. m = m / N
  4. i = i + 1,并重复步骤2~步骤4,直到m == 0
  5. d[k]d[k-1]……d[1]d[0]即为mN进制表示。

  为了演示简单,此处假设2 <= N <= 10C++代码如下:


// Conver.h
#include <string>
namespace Convert {
    std::string DecimalToBaseN(unsigned int d, int convertBase);
};
// Conver.cpp
#include <string>
namespace Convert {
    std::string DecimalToBaseN(unsigned int d, int convertBase)
    {
        if (d == 0 || convertBase < 2 || convertBase > 10) {
            return "0";
        }

        std::string result;
        while (d > 0) {
            result += ('0' + d % convertBase);
            d /= convertBase;
        }

        std::reverse(result.begin(), result.end());
        return result;
    }
};
// test.cpp
#include <iostream>
#include "Convert.h"
int main(int argc, char **argv)
{
    std::cout << "15 to base-2 is: " << Convert::DecimalToBaseN(15, 2) << std::endl;
    std::cout << "15 to base-3 is: " << Convert::DecimalToBaseN(15, 3) << std::endl;
    std::cout << "15 to base-4 is: " << Convert::DecimalToBaseN(15, 4) << std::endl;
    std::cout << "15 to base-5 is: " << Convert::DecimalToBaseN(15, 5) << std::endl;
    std::cout << "15 to base-6 is: " << Convert::DecimalToBaseN(15, 6) << std::endl;
    std::cout << "15 to base-7 is: " << Convert::DecimalToBaseN(15, 7) << std::endl;
    std::cout << "15 to base-8 is: " << Convert::DecimalToBaseN(15, 8) << std::endl;
    std::cout << "15 to base-9 is: " << Convert::DecimalToBaseN(15, 9) << std::endl;
    std::cout << "15 to base-10 is: " << Convert::DecimalToBaseN(15, 10) << std::endl;
    return 0;
}
// 执行结果
15 to base-2 is: 1111
15 to base-3 is: 120
15 to base-4 is: 33
15 to base-5 is: 30
15 to base-6 is: 23
15 to base-7 is: 21
15 to base-8 is: 17
15 to base-9 is: 16
15 to base-10 is: 15

  • N进制转换成十进制,可以通过如下步骤来得到:
  1. 假设N进制的数表示为d[k]d[k-1]……d[1]d[0],初始时i = k,转换结果存储在result中;
  2. result = result * N + (d[i] - '0')
  3. i = i - 1,重复步骤2~步骤3,当i < 0时,转换终止。
  4. result即为转换后的结果。

  同样也假设2 <= N <= 10C++代码如下:


// Conver.h
#include <string>
namespace Convert {
    unsigned int BaseNToDecimal(const std::string &bn, int convertBase);
};
// Conver.cpp
#include <string>
namespace Convert {
    unsigned int BaseNToDecimal(const std::string &bn, int convertBase)
    {
        if (bn.size() == 0) {
            return 0;
        }

        unsigned int result = 0;
        for (const auto &c : bn) {
            result = result * convertBase + (c - '0');
        }

        return result;
    }
};
// test.cpp
#include <iostream>
#include "Convert.h"
int main(int argc, char **argv)
{
    std::cout << "Base-2 1111 to decimal is: " << Convert::BaseNToDecimal("1111", 2) << std::endl;
    std::cout << "Base-3 120 to decimal is: " << Convert::BaseNToDecimal("120", 3) << std::endl;
    std::cout << "Base-4 33 to decimal is: " << Convert::BaseNToDecimal("33", 4) << std::endl;
    std::cout << "Base-5 30 to decimal is: " << Convert::BaseNToDecimal("30", 5) << std::endl;
    std::cout << "Base-6 23 to decimal is: " << Convert::BaseNToDecimal("23", 6) << std::endl;
    std::cout << "Base-7 21 to decimal is: " << Convert::BaseNToDecimal("21", 7) << std::endl;
    std::cout << "Base-8 17 to decimal is: " << Convert::BaseNToDecimal("17", 8) << std::endl;
    std::cout << "Base-9 16 to decimal is: " << Convert::BaseNToDecimal("16", 9) << std::endl;
    std::cout << "Base-10 15 to decimal is: " << Convert::BaseNToDecimal("15", 10) << std::endl;
    return 0;
}
// 执行结果
Base-2 1111 to decimal is: 15
Base-3 120 to decimal is: 15
Base-4 33 to decimal is: 15
Base-5 30 to decimal is: 15
Base-6 23 to decimal is: 15
Base-7 21 to decimal is: 15
Base-8 17 to decimal is: 15
Base-9 16 to decimal is: 15
Base-10 15 to decimal is: 15

五、结束

  前面讨论的非负整数的10进制以内的N进制与10进制互相转换,有几个扩展问题可以思考一下:

  • 对于负整数,转换过程有何区别?
  • 对于大于10进制的转换,该如何处理?
  • 对于N进制与M进制互相转换,该如何处理?
最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 220,458评论 6 513
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 94,030评论 3 396
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 166,879评论 0 358
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 59,278评论 1 295
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 68,296评论 6 397
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 52,019评论 1 308
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 40,633评论 3 420
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 39,541评论 0 276
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 46,068评论 1 319
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 38,181评论 3 340
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 40,318评论 1 352
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 35,991评论 5 347
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 41,670评论 3 331
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 32,183评论 0 23
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 33,302评论 1 272
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 48,655评论 3 375
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 45,327评论 2 358