C++入门教程(15):数字与进制

小古银的官方网站(完整教程):http://www.xiaoguyin.com/
C++入门教程视频:https://www.bilibili.com/video/av20868986/


前言

当你完成上一部分教程的全部练习后,相信你应该可以灵活地使用C++去解决大部分问题,尤其是数学问题。

本部分教程将讲解C++中必须知道的计算机基础知识,知道这些知识可以避免不少的错误,还可以对程序代码进一步优化。由于这部分教程只讲解C++需要知道的计算机基础知识,所以并不会太多和太复杂。

计算机处理数据是由电路控制的,电路只有两种状态:,因此计算机上的所有数据都是二进制的数据,然后用一定的规则将这些数据表示成十进制数字、文字、图片和其他各种各样的形式,所以接下来的内容都是围绕二进制而讲解的。

学习这部分教程才能更好地理解后续的教程,只要用心地去学就不会有问题。这部分知识了解即可不必深入,如果有兴趣,深入也无妨。


在讲解二进制相关知识前,先讲解C++中数值的各种表示方式和各种操作。

数字分位符

写代码的时候,难免会遇到一些比较大的数。用一个很小的数做例子,例如先赚它一个亿(●'◡'●)。那么我们写代码的时候,一亿在代码中的写法是100000000

为了方便阅读数字,可以用单引号'分隔一下,这个单引号叫做数字分位符。一亿就可以写成这样子:1'0000'0000,一看就知道一亿。

先看以下代码:

#include <iostream>

int main(void)
{
    std::cout << "一亿:" << 1'0000'0000 << std::endl;
    std::cout << "一百万:" << 1'000'000 << std::endl;
    std::cout << "这种写法就不好了:" << 1'000'0'0'00'0 << std::endl;
    return 0;
}

输出结果:

一亿:100000000
一百万:1000000
这种写法就不好了:100000000

输出还是正常的数值输出,不会在输出的数值里显示数字分位符,因为数字分位符是为了方便阅读代码而出现的。但是第三种写法并不能方便阅读代码,所以不是一个好的写法。

整数进制

对于一个十进制的15,可以表示成二进制的1111,也可以表示成八进制的17,也可以表示成十六进制的F。尽管15111117F看上去不一样,但是它们都是同一个整数,只是表示方法不一样。

先看以下例子:

#include <iostream>

int main(void)
{
    // 以下是十进制的15的各种表示方式
    std::cout << 0b1111 << std::endl; // 输出二进制
    std::cout << 017 << std::endl; // 输出八进制
    std::cout << 15 << std::endl; // 输出十进制
    std::cout << 0xF << std::endl; // 输出十六进制
    return 0;
}

输出结果:

15
15
15
15

可以看到它们都是输出15,因为它们都是同一个数字的不同表示方法,而std::cout默认以十进制显示,所以都显示15

在代码中,默认以十进制来表示数字,如果要用其他进制表示一个数字,需要一些特殊的说明:

  • 二进制需要在数字的前面加上0b或者0B,例如要用二进制的110:0b110
  • 八进制需要在数字的前面加上0,例如要用八进制的6:06
  • 十进制是默认的表示方法,不需要特殊说明。
  • 十六进制需要在数字的前面加上0x或者0X,例如要用十六进制的6:0x6

至于为什么不只是用十进制,还要添加这么多表示方式,其实很简单,因为有一些数学运算,有时候,不用十进制而用其他进制运算更加容易理解,方便程序员做数学运算。初学者只要理解并背下来,以后将会用得上。

有时候,当用十六进制运算完后,极有可能想看看十六进制的结果,然而,std::cout默认显示的是十进制。这时候,我们就要告诉std::cout我要用十六进制显示。

先看下面例子:

#include <iostream>

int main(void)
{
    std::cout << "十六进制 11 + 22 的结果是:" << std::endl; // 输出文字
    std::cout << "默认:" << (0x11 + 0x22) << std::endl; // 默认十进制显示
    std::cout << "八进制:" << std::oct << (0x11 + 0x22) << std::endl; // 八进制显示
    std::cout << "十六进制:" << std::hex << (0x11 + 0x22) << std::endl; // 十六进制显示
    std::cout << "十进制:" << std::dec << (0x11 + 0x22) << std::endl; // 改回十进制显示
    return 0;
}

输出结果:

十六进制 11 + 22 的结果是:
默认:51
八进制:63
十六进制:33
十进制:51

当我们需要输出八进制时,需要先输出std::oct;当我们需要输出十六进制时,需要先输出std::hex。如果想再次输出十进制,就必须要先输出std::dec;否则,将会继续以前一次使用的进制(上面代码就是十六进制)来输出。其中std::octstd::decstd::hexiostream库中。

仔细的你应该发现了,我没有写二进制输出。二进制的输出方法跟上面的有些不同,因为std::cout没有直接的二进制输出。如果想输出二进制数字,则可以使用std::bitset,它在bitset标准库中。使用std::bitset<二进制的位数>(数字)就可以输出二进制了,具体用法如下:

#include <iostream> // std::cout std::endl
#include <bitset> // std::bitset

int main(void)
{
    std::cout << "十六进制 11 + 22 的结果是:" << std::endl; // 输出文字
    std::cout << "二进制:" << std::bitset<8>(0x11 + 0x22) << std::endl; // 二进制显示
    std::cout << "默认:" << 0x11 + 0x22 << std::endl; // 默认十进制显示
    return 0;
}

输出结果:

十六进制 11 + 22 的结果是:
二进制:00110011
默认:51

由于这次输出不改变std::cout的行为,所以默认还是输出十进制:

std::cout << "默认:" << 0x11 + 0x22 << std::endl;

代码中,std::bitset<8>(0x11 + 0x22)指定了8位二进制(不足8位则在左边用0补够8位):

浮点型

浮点型即小数。

浮点型的表示方法

  • 普通的表示方法:3.14.2(即0.2)、10.(即10.0)。
  • 科学记数法:2e2(即 2.0 * 10^2 = 200.0),0x1.p10(即 1.0 * 2^10 = 1024.0)
  • 十六进制与科学记数法:0xf.p-10xf.即十进制的15.00xf.p-1即 15.0 * 2^(-1) = 7.5)、0xa.bp100xa.b即十进制的10.68750xa.bp10即 10.6875 * 2^10 = 10944.0)

同样,输出显示十六进制浮点型需要先输出std::hexfloat,它在iostream标准库中:

#include <iostream>

int main(void)
{
    std::cout << std::dec << 0xf.p1 << std::endl; // 十进制的30.0
    std::cout << std::hexfloat << 0xf.p1 << std::endl; // 十进制的30.0
    return 0;
}

输出结果:

30
0x1.e00000p+4

补充知识(了解即可)

  1. 数字分位符从C++11开始加入。
  2. 二进制表示法(即0b)从C++11开始加入。
  3. 十六进制的浮点型表示方法和十六进制的浮点型科学记数法从C++17开始加入。
  4. std::hexfloat从C++17开始加入。

巩固练习

输入三个整数abc,然后分别按顺序以八进制,十进制,十六进制的表示方法,输出这三个整数的和。

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