• Loren Blog

  • Menu
  • 无符号数的编码
    • 转换公式
  • 2的补码编码
    • 转换公式
  • 1的补码编码
    • 转换公式
  • 原码
    • 转换公式
  • 无符号数 和 2的补码之间的转换
  • 其他
    • C语言中数字扩展
    • C语言中数字截断

    1的补码与2的补码

    假设对于一个整数 x,有 n 位,用 v 表示这个位向量。

    无符号数的编码

    转换公式

    B2U<n>(v) = v[i] * pow(2, i) for 0 ..^ v

    例子

    B2U<4>([0001]) = v[3] * pow(2, 3) ... = 0 * 8 + 0 * 4 + 0 * 2 + 1 * 1 = 1
    B2U<4>([1011]) = v[3] * pow(2, 3) ... = 1 * 8 + 0 * 4 + 1 * 2 + 1 * 1 = 11

    函数 B2U<n> 是一个双射,长度为 n 的向量与整数 是一一对应的关系。

    2的补码编码

    即是我们常说的补码(Two’s Complement)。

    转换公式

    B2T<n>(v) = - v[n - 1] * pow(2, n - 1) + v[i] * pow(2, i) for 0 .. (v - 2)

    例子

    B2T<4>([0001]) = ... = - 0 * 8 + 0 * 4 + 0 * 2 + 1 * 1 = 1
    B2T<4>([1011]) = ... = - 1 * 8 + 0 * 4 + 1 * 2 + 1 * 1 = -5

    v 的最高位称为符号位,它的“权重”为 -pow(2, n - 1), 为 1 时表示值为负,0 为正。

    函数 B2T<n> 也是一个双射,长度为 n 的向量与整数 是一一对应的关系。

    1的补码编码

    即我们常说的反码(Ones' Complement, 注意 Two’s Complement 撇号的位置)。

    转换公式

    B2O<n>(v) = - v[n - 1] * (pow(2, n - 1) - 1) + v[i] * pow(2, i) for 0 .. (v - 2)

    例子

    B2O<4>([0001]) = ... = - 0 * 7 + 0 * 4 + 0 * 2 + 1 * 1 = + 1
    B2O<4>([1011]) = ... = - 1 * 7 + 0 * 4 + 1 * 2 + 1 * 1 = - 4
    B2O<4>([1111]) = ... = - 1 * 7 + 1 * 4 + 1 * 2 + 1 * 1 = - 0
    B2O<4>([0000]) = ... = - 0 * 7 + 0 * 4 + 0 * 2 + 0 * 1 = + 0

    v 的最高位称为符号位,它的“权重”为 -(pow(2, n - 1) - 1), 为 1 时表示值为负,0 为正,其他与 2的补码 一致。

    原码

    即我们常说的原码(Sign-Magnitude)。

    转换公式

    B2S<n>(v) = pow(-1, v[n - 1]) + v[i] * pow(2, i) for 0 .. (v - 2)

    例子

    B2S<4>([0001]) = ... = pow(-1, 0) * (0 * 4 + 0 * 2 + 1 * 1) = + 1
    B2S<4>([1011]) = ... = pow(-1, 1) * (0 * 4 + 1 * 2 + 1 * 1) = - 3
    B2S<4>([1111]) = ... = pow(-1, 1) * (1 * 4 + 1 * 2 + 1 * 1) = - 7
    B2S<4>([0000]) = ... = pow(-1, 0) * (0 * 4 + 0 * 2 + 0 * 1) = + 0
    B2S<4>([1000]) = ... = pow(-1, 1) * (0 * 4 + 0 * 2 + 0 * 1) = - 0

    v 的最高位依然是符号位,用于确定剩下的位表示负数还是正数。

    无符号数 和 2的补码之间的转换

    此转换即是 C语言 中 有符号数 和 无符号数 之间的转换规则,C语言 中 无符号数 和 有符号数 的转换原则是保持 位表示 不变。

    T2U<n>(x) = { x < 0 => x + pow(2, n) || x >= 0 => x }
       U2T<n>(u) = { u > pow(2, n - 1) => u || u >= pow(2, n - 1) => u - pow(2, n) }

    其他

    C语言中数字扩展

    • 将 无符号数 转换为更大的数据类型时,只需要在位的开头添加 0 即可,这种运算称为 零扩展(Zero Extension)。

    • 将 有符号数 转换为更大的数据类型时,规则是在开头添加最高有效位的副本,这种运算称为 符号扩展(Sign Extension)。

      [ x[n - 1], x[n - 2], ... x[0] ] => [ x[n - 1], x[n - 1], x[n - 1] ... x[n - 1], x[n - 2], ... x[0] ]

    C语言中数字截断

    当对一个 n 位的数字 v0 = [ x[n - 1], x[n - 2], …​ x[0] ] 截断 为 k 位时,会丢弃高 n ~ k 位,得到另一个位 向量 v1 = [ x[k - 1], x[k - 2], …​ x[0] ],运算结果是 x mod pow(2, k)

    即

    • 无符号数 ⇒ B2U<k>(v1) = B2U<n>(v0) mod pow(2, k)

    • 有符号数 ⇒ B2T<k>(v1) = U2T<k>(B2U<n>(v0) mod pow(2, k))

Posts

  • Perl6的符号表
  • Perl6调用C接口
  • 插件生命周期(QtCreator文档翻译)
  • 1的补码与2的补码
  • 归纳操作符(reduce operator)
  • emacs config
  • c++模板的技巧示例
  • 简单括号匹配
  • IA-32算术移位与逻辑移位
Loren Blog

将会写一些关于C/C++/Perl6 的小文章,记录一些知识点。


© 2017 araraloren | araraloren@github.com