【问题标题】:Unsigned / Signed Arithmetic Problems from A Programmer's Perspective Textbook程序员视角教科书中的无符号/有符号算术问题
【发布时间】:2017-08-19 09:27:35
【问题描述】:
int x = random();
int y = random();

unsigned ux = (unsigned) x;
unsigned uy = (unsigned) y;

对于以下每个 C 表达式,你要指出是否 不是表达式总是产生 1。如果它总是产生 1,请描述基本的数学原理。否则,请给出一个使其产生 0 的参数示例。

A. (x<y) == (-x>-y) 
B. ((x+y)<<4) + y-x == 17*y+15*x
C. ~x+~y+1 == ~(x+y)
D. (ux-uy) == -(unsigned)(y-x)
E. ((x >> 2) << 2) <= x

对于这些问题,我知道只有 A 可以产生 0,而其余的总是产生 1。

我知道这可能是错误的,我不是在寻找直接的答案,但我希望获得一些关于如何解决这些问题的一般知识/建议。

我有一位非常糟糕的教授,我一直在尝试在线查找资源,但我真的不知道从哪里开始或寻找什么。我知道无符号/二进制补码算术和位移的基础知识,但我不知道如何应用它来找到这些问题的反例。

【问题讨论】:

  • A 应始终为 1 ...
  • 如果x == INT_MIN(例如)可能不是因为-INT_MIN 在使用二进制补码表示的机器上不能表示为int(几乎所有现代计算机都这样做)。在这种情况下,表达式将导致未定义的行为(不仅仅是具有未指定的值)。
  • 事实上,对于除 D 之外的所有表达式,都存在 xy 的值,它们会导致未定义的行为或具有未指定的值,从而使问题无法回答,因为它们可能或者可能不会为这些值产生 0 或完全做其他事情。我怀疑这本书不知道有符号整数溢出(也没有符号位移)的规则,只是假设编译器不会基于它们进行优化。根据这样的假设,FreeBSD 是 recently bitten
  • 哦,对于 D 也是如此,例如y = INT_MINx = 1(导致表达式右侧的整数下溢,从而导致未定义的行为)。当我写最后一条评论时,我读到好像uxuy 被用于右侧和左侧。
  • @Wintermute 我刚刚用 D 的这些值进行了测试,它仍然适用于我。我认为我们假设该值会换行/被截断?不确定这是否是它起作用的原因。

标签: c bit-manipulation unsigned twos-complement


【解决方案1】:

C 编程语言没有指定整数有符号量溢出的结果;如果x 是有符号且为负数,它也不会定义x &lt;&lt; n

但是,算术运算不考虑符号而执行的情况并不少见,考虑到有符号和无符号 n 位整数都是以二进制补码系统表示的模 2^n 的数字。

这必须假设为您的练习,否则几乎没有意义。

8 位整数示例:

unsigned domain: (0..127), ( 128..255)
signed   domain: (0..127), (-128..-1)

二进制表示:

unsigned domain: 00000000..01111111 and 10000000..11111111
signed   domain: 00000000..01111111 and 10000000..11111111

有符号和无符号之间,只有整数的代表系统 模 2^n 不同,这与打印相关,但与内部无关 计算(只要只使用+-* 和按位运算)。

对于有符号整数,负整数的第一位设置为 1. 有符号和无符号之间的转换是无关的,除了打印。

我坚持,这是假设你的练习,但 C 编程语言 没有具体说明我的大部分声明。

A. (x&lt;y) == (-x&gt;-y)

x == INT_MINy == INT_MIN + 1反驳, 因为INT_MIN == -INT_MIN

B. ((x+y)&lt;&lt;4) + y-x == 17*y+15*x

正确:

   ((x+y) << 4     ) + y-x
== ((x+y) * 0x10000) + y-x
== ((x+y) * 16     ) + y-x
== 17 * y + 15 * x

C. ~x+~y+1 == ~(x+y)

正确:

x + ~x + 1 == 0
~x + 1 == -x
~(x+y) + 1 == -(x+y)
~(x+y) + 1 == -x + -y
~(x+y) + 1 == ~x + 1 + ~y + 1
~(x+y) == ~x + ~y + 1

D. ((unsigned)x-(unsigned)y) == -(unsigned)(y-x)

True:假设从有符号到无符号的转换不会改变内部 表示,并且假设运算符忽略 整数。换句话说,x-y == -(y-x) 在任何放置演员表的地方都成立。

E. ((x &gt;&gt; 2) &lt;&lt; 2) &lt;= x

正确:

   x 
== (x >> 2) << 2 + two_last_significant_bits_of_x
== (x >> 2) << 2 + positive
>= (x >> 2) << 2

带符号 32 位整数的示例:

x              == 5
x              == 00000000000000000000000000000101 in base2
x >> 2         == 00000000000000000000000000000001 in base2
(x >> 2) << 2  == 00000000000000000000000000000100 in base2
(x >> 2) << 2  == 4

x              == -5
x              == 11111111111111111111111111111011 in base2
x >> 2         == 11111111111111111111111111111110 in base2
(x >> 2) << 2  == 11111111111111111111111111111000 in base2
(x >> 2) << 2  == -8

【讨论】:

  • 我确实认为您对 C 的回答不正确,通过将 x 和 y 都设为 0,左侧将评估为 3,右侧为 1。感谢您提供完整且写得好的答案无论如何!
  • @JeffreyCordero 在带有x == 0y == 0 的C 中,双方都计算为-1,其位均为1。
  • @Loic in C 我认为“换句话说,x-y == -(x-y) 在任何地方都成立。”应该说“换句话说,x-y == -(y-x) 在任何地方都成立。”
猜你喜欢
  • 2010-12-16
  • 2010-10-08
  • 1970-01-01
  • 2014-10-04
  • 1970-01-01
  • 2011-06-23
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多