C语言二级备考1-1.2

C语言中的正负数及其输出

在数学中,数字有正负之分。在C语言中也是一样,short、int、long 都可以带上正负号,例如:

/负数
short a1 = -10;
short a2 = -0x2dc9;  //十六进制
//正数
int b1 = +10;
int b2 = +0174;  //八进制
int b3 = 22910;
//负数和正数相加
long c = (-9) + (+12);

如果不带正负号,默认就是正数。

符号也是数字的一部分,也要在内存中体现出来。
符号只有正负两种情况,用1位(Bit)就足以表示;C语言规定,把内存的最高位作为符号位。以 int 为例,它占用 32 位的内存,0~30 位表示数值,31 位表示正负号。如下图所示:


注·这里的31就是第32位,0就是第一位。

C语言规定,在符号位中,用 0 表示正数,用 1 表示负数。例如 int 类型的 -10 和 +16 在内存中的表示如下:

short、int 和 long 类型默认都是带符号位的,符号位以外的内存才是数值位。如果只考虑正数,那么各种类型能表示的数值范围(取值范围)就比原来小了一半。

  • 打个比方,1字节(Byte)由8个位(bit)组成。那么他最大就可以表示255。假如第一位变成了0,那他最大就只能表127。

但是在很多情况下,我们非常确定某个数字只能是正数,比如班级学生的人数、字符串的长度、内存地址等,这个时候符号位就是多余的了,就不如删掉符号位,把所有的位都用来存储数值,这样能表示的数值范围更大(大一倍)。

C语言允许我们这样做,如果不希望设置符号位,可以在数据类型前面加上 unsigned 关键字,例如:

unsigned short a = 12;
unsigned int b = 1002;
unsigned long c = 9892320;

如果是unsigned int类型,那么可以省略 int ,只写 unsigned。

整数在内存中是如何存储的

在计算机中,有符号数在存储和读取时都要进行转化。

源码

将一个整数转换成二进制形式,就是其原码。
例如short a = 6;a的原码就是----- 0000 0000 0000 0110;
更改a的值a = -18,此时a的原码就是--1000 0000 0001 0010。

反码

谈到反码,需要将正数负数区别对待,因为它们的反码不一样。
对于正数,它的反码就是其原码(原码和反码相同)。

负数的反码就是将原码中除符号位以外的所有位(数值位)取反。
也就是0变成1,1变成0。
例如short a = 6,a的原码和反码都是0000 0000 0000 0110
更改a的值a = -18,此时a的反码是 1111 1111 1110 1101

补码

对于正数,它的补码就是其原码(原码、反码、补码都相同)。
负数的补码是其反码加 1
例如:
short a = 6;a 的原码、反码、补码都是0000 0000 0000 0110;
更改 a 的值a = -18;,此时 a 的补码是1111 1111 1110 1110。
 原码、反码、补码的概念只对负数有实际意义,对于正数,它们都一样。最后我们总结一下 6 和 -18 从原码到补码的转换过程:

  • 注:在计算机内存中,整数一律采用补码的形式来存储。这意味着,当读取整数时还要采用逆向的转换,也就是将补码转换为原码。
    将补码转换为原码也很简单:先减去 1,再将数值位取反即可。

    C语言中的小数

    C语言中小数的指数形式为:
    aEn 或 aen
    a 为尾数部分,是一个十进制数;n 为指数部分,是一个十进制整数;E或e是固定的字符,用于分割尾数部分和指数部分。
    整个表达式等价于 a×10n。
    指数形式的小数举例:

  • 2.1E5 = 2.1×105,其中 2.1 是尾数,5 是指数。
  • 3.7E-2 = 3.7×10-2,其中 3.7 是尾数,-2 是指数。
  • 0.5E7 = 0.5×107,其中 0.5 是尾数,7 是指数。

C语言中常用的小数有两种类型,分别是 float 或 double;
float 称为单精度浮点型,double 称为双精度浮点型。

  • 注:float 始终占用4个字节,double 始终占用8个字节。

    小数输出形式

    小数也可以使用 printf 函数输出,包括十进制形式和指数形式,它们对应的格式控制符分别是:

  • %f 以十进制形式输出 float 类型;
  • %lf 以十进制形式输出 double 类型
  • %e 以指数形式输出 float 类型,输出结果中的 e 小写;
  • %E 以指数形式输出 float 类型,输出结果中的 E 大写;
  • %le 以指数形式输出 double 类型,输出结果中的 e 小写;
  • %lE 以指数形式输出 double 类型,输出结果中的 E 大写。

    #include <stdio.h>
    #include <stdlib.h>
    int main()
    {
    float a = 0.302;
    float b = 128.101;
    double c = 123;
    float d = 112.64E3;
    double e = 0.7623e-2;
    float f = 1.23002398;
    printf("a=%e \n b=%f \n c=%lf \n d=%lE \n e=%lf \n f=%f\n", a, b, c, d, e, f);
    
    return 0;
    }

    ----------->结果如下:

    image-20230301100130634

    注意:

  • %f 和 %lf 默认保留六位小数,不足六位以 0 补齐,超过六位按四舍五入截断。
  • 将整数赋值给 float 变量时会变成小数。
  • 以指数形式输出小数时,输出结果为科学计数法;也就是说,尾数部分的取值为:0 ≤ 尾数 < 10。

    %g

    %g 会对比小数的十进制形式和指数形式,以最短的方式来输出小数,让输出结果更加简练。所谓最短,就是输出结果占用最少的字符。

#include <stdio.h>
#include <stdlib.h>
int main()
{
    float a = 0.00001;
    float b = 30000000;
    float c = 12.84;
    float d = 1.229338455;
    printf("a=%g \nb=%g \nc=%g \nd=%g\n", a, b, c, d);

    return 0;
}

///运行结果:
a=1e-05
b=3e+07
c=12.84
d=1.22934

注:

  • %g 默认最多保留六位有效数字,包括整数部分和小数部分;%f 和 %e 默认保留六位小数,只包括小数部分。
  • %g 不会在最后强加 0 来凑够有效数字的位数,而 %f 和 %e 会在最后强加 0 来凑够小数部分的位数。
  • %g 和 %lg 分别用来输出 float 类型和 double 类型,并且当以指数形式输出时,e小写。
  • %G 和 %lG 也分别用来输出 float 类型和 double 类型,只是当以指数形式输出时,E大写。

评论

  1. 3周前
    2023-3-02 4:31:16

    Thanks for share!

发送评论 编辑评论


				
|´・ω・)ノ
ヾ(≧∇≦*)ゝ
(☆ω☆)
(╯‵□′)╯︵┴─┴
 ̄﹃ ̄
(/ω\)
∠( ᐛ 」∠)_
(๑•̀ㅁ•́ฅ)
→_→
୧(๑•̀⌄•́๑)૭
٩(ˊᗜˋ*)و
(ノ°ο°)ノ
(´இ皿இ`)
⌇●﹏●⌇
(ฅ´ω`ฅ)
(╯°A°)╯︵○○○
φ( ̄∇ ̄o)
ヾ(´・ ・`。)ノ"
( ง ᵒ̌皿ᵒ̌)ง⁼³₌₃
(ó﹏ò。)
Σ(っ °Д °;)っ
( ,,´・ω・)ノ"(´っω・`。)
╮(╯▽╰)╭
o(*////▽////*)q
>﹏<
( ๑´•ω•) "(ㆆᴗㆆ)
😂
😀
😅
😊
🙂
🙃
😌
😍
😘
😜
😝
😏
😒
🙄
😳
😡
😔
😫
😱
😭
💩
👻
🙌
🖕
👍
👫
👬
👭
🌚
🌝
🙈
💊
😶
🙏
🍦
🍉
😣
Source: github.com/k4yt3x/flowerhd
颜文字
Emoji
小恐龙
花!
上一篇
下一篇