Skip to content

Precheck 1:C语言与数值表示

概念介绍

由于计算机内部通常使用二进制,而我们人类倾向于使用十进制,我们提出了一些表示方案,以便在人类概念的数字和计算机之间轻松转换。以下是一些最常见的表示方式:

无符号数

如果我们有一个 \(n\) 位无符号数字 \(d_{n-1}d_{n-2}\cdots d_0\),基数(或进制)为 \(r\),则该数字的值为:
$$ \sum_{i=0}^{n-1} r^i d_i, $$
这相当于将十进制的“十位”“百位”换成了 \(r\) 的幂次位。对于三种常见进制:二进制、十进制和十六进制,我们将 \(r\) 分别设为 2、10 和 16。

有符号数

无符号二进制数可表示自然数,但许多计算需要负数。为此,使用了多种方案来表示有符号数。以下是两种常见的方案:

补码

  1. 一个 \(n\) 位补码的数值可表示为:
    $$ \sum_{i=0}^{n-2} 2^i d_i \;-\; 2^{n-1}\,d_{n-1}. $$

  2. 负数的最高有效位(MSB)为 1。将 \(d_{n-1}=1\) 代入上式,得到:
    $$ \sum_{i=0}^{n-2} 2^i d_i \;-\; 2^{n-1}. $$

  3. 正数的 MSB 为 0。将 \(d_{n-1}=0\) 代入,得到:
    $$ \sum_{i=0}^{n-2} 2^i d_i, $$
    与无符号数完全相同。
  4. 要取反(求相反数):对所有位取反后再加 1。
  5. 加法运算与无符号数相同。
  6. 只有一个零,表示为 `0b0`。

移码

  1. 将数值线性平移,使得要表示的最小数值对应二进制 `0...0`。
  2. 若要得到实际数值,则将表示当作无符号数读取,再加上偏移值。
  3. 可根据需求选择任意偏移。对于 \(N\) 位,为了对称地表示负数和正数,常用的偏移为
    $$ -(2^{N-1}-1). $$

数值表示

  1. 在不同的上下文中,相同的比特序列可能表示不同的内容。

    答案

    正确。相同的比特在完全相同的情况下可以有多种不同的解释!这些比特可以表示无符号数、有符号数,甚至在我们之后将要学习的内容中,还可以表示一个程序。关键在于对它的解释是否达成了一致。

  2. 当用补码对两个符号相反的数进行加法时,可能会发生溢出。

    答案

    错误。 溢出错误只会在加法的正确结果超出范围 \([-(2^{n-1}), \quad 2^{n-1} - 1]\) 时发生。给符号相反的数相加不会导致结果超出这个范围。

  3. 如果将一个 \(N\) 位的补码按无符号数解释,那么负数会被解释为小于正数的值。

    答案

    错误。在补码表示法中,负数的最高有效位(MSB)总是 1。这意味着每一个负数在转换为无符号数时,其值都会比所有正数更大。

  4. 如果将一个 \(N\) 位的移码按无符号数解释(假设存在负数时的偏移量),那么负数会被解释为小于正数的值。

    答案

    正确。在移码表示法中,我们通过给无符号数加上一个偏移值来表示数值。无论我们如何“平移”可表示值的范围,负数在转换为无符号数时,总是比正数小。这一点不同于补码(见上文说明)。

  5. 我们可以在给定的数值表示格式(无符号、偏移和补码)中表示分数和小数。

    答案

    错误。我们目前的表示格式有一个主要的限制:只能表示整数并对整数进行运算。要想成功表示小数以及超出当前范围的极大数值,我们需要另一种表示格式。

C 语言

  1. 声明字符数组的正确方式是 char[] array

    答案

    错误。正确的写法是 char array[]

  2. C 是按值传递语言。

    答案

    正确。如果你想传递引用(reference),应该使用指针。