将 int 转换为 unsigned 的计算复杂度与比较值的复杂度
Computational complexity for casting int to unsigned vs complexity for comparing values
我只是想知道 C/C++ 中哪个操作更快,以及类型转换的计算复杂度是多少。
将 x 类型转换为无符号整数,如下所示:
(unsigned int) x
或
正在对 x 和常量进行比较:
x<0
编辑:计算复杂性,因为为了成功执行指令,哪个过程需要在硬件的低级方面进行最少的位操作。
编辑 #2: 所以为了提供一些背景信息,我特别想做的是看看是否减少
if( x < 0)
进入
if((((unsigned int)x)>>(((sizeof(int))<<3)-1)))
如果超过 100,000,000 次,x 的数量很大,above/below (+/-)50,000,000
是否会更有效率
(unsigned int) x
是 - 对于 near-universal 2 的补码 - 编译时操作:你告诉编译器将 x
的内容视为 unsigned
值,它本身不需要任何运行时 machine-code 指令,但可能会更改它发出的机器代码指令以支持对 unsigned
值的使用,甚至导致 dead-code 消除优化,例如以下可以在转换后完全消除:
if ((unsigned int)my_unsigned_int >= 0)
相关的 C++ 标准引用(我的粗体):
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s
complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]
可能存在实际的按位更改,需要使用 1 的补码或 sign/magnitude 表示对某些奇怪的硬件进行操作。 (感谢 Yuushi 在评论中强调这一点)。
这与 x < 0
形成对比,后者 - 对于编译器没有特殊知识的带符号 x
,确实需要 CPU/machine-code 指令来评估(如果使用结果) 和相应的运行时。该比较指令在更早的 CPU 上往往需要 1 "cycle",但请记住,现代 CPU 管道可以在单个周期内并行执行许多此类指令。
if( x < 0)
vs if((((unsigned int)x)>>(((sizeof(int))<<3)-1)))
- faster?
第一个总是至少和第二个一样快。与零的比较是 CPU 的 bread-and-butter 操作,并且 C++ 编译器肯定会为其使用高效的操作码(机器代码指令):您正在浪费时间来改进它。
要回答您实际编辑的问题,它不太可能更快。在最好的情况下,如果 x
在编译时已知,编译器将能够在这两种情况下完全优化分支。
如果 x
是一个 run-time 值,那么第一个将产生一个测试指令。第二个可能会产生一个 shift-right 立即数,然后是一个测试指令。
怪物 if((((unsigned int)x)>>(((sizeof(int))<<3)-1)))
会比直接的慢 if(x < 0)
: 两个版本都需要将一个值与零进行比较,但是你的怪物在比较之前添加了一个移位。
我只是想知道 C/C++ 中哪个操作更快,以及类型转换的计算复杂度是多少。
将 x 类型转换为无符号整数,如下所示:
(unsigned int) x
或
正在对 x 和常量进行比较:
x<0
编辑:计算复杂性,因为为了成功执行指令,哪个过程需要在硬件的低级方面进行最少的位操作。
编辑 #2: 所以为了提供一些背景信息,我特别想做的是看看是否减少
if( x < 0)
进入
if((((unsigned int)x)>>(((sizeof(int))<<3)-1)))
如果超过 100,000,000 次,x 的数量很大,above/below (+/-)50,000,000
是否会更有效率(unsigned int) x
是 - 对于 near-universal 2 的补码 - 编译时操作:你告诉编译器将 x
的内容视为 unsigned
值,它本身不需要任何运行时 machine-code 指令,但可能会更改它发出的机器代码指令以支持对 unsigned
值的使用,甚至导致 dead-code 消除优化,例如以下可以在转换后完全消除:
if ((unsigned int)my_unsigned_int >= 0)
相关的 C++ 标准引用(我的粗体):
If the destination type is unsigned, the resulting value is the least unsigned integer congruent to the source integer (modulo 2n where n is the number of bits used to represent the unsigned type). [ Note: In a two’s complement representation, this conversion is conceptual and there is no change in the bit pattern (if there is no truncation). —end note ]
可能存在实际的按位更改,需要使用 1 的补码或 sign/magnitude 表示对某些奇怪的硬件进行操作。 (感谢 Yuushi 在评论中强调这一点)。
这与 x < 0
形成对比,后者 - 对于编译器没有特殊知识的带符号 x
,确实需要 CPU/machine-code 指令来评估(如果使用结果) 和相应的运行时。该比较指令在更早的 CPU 上往往需要 1 "cycle",但请记住,现代 CPU 管道可以在单个周期内并行执行许多此类指令。
if( x < 0)
vsif((((unsigned int)x)>>(((sizeof(int))<<3)-1)))
- faster?
第一个总是至少和第二个一样快。与零的比较是 CPU 的 bread-and-butter 操作,并且 C++ 编译器肯定会为其使用高效的操作码(机器代码指令):您正在浪费时间来改进它。
要回答您实际编辑的问题,它不太可能更快。在最好的情况下,如果 x
在编译时已知,编译器将能够在这两种情况下完全优化分支。
如果 x
是一个 run-time 值,那么第一个将产生一个测试指令。第二个可能会产生一个 shift-right 立即数,然后是一个测试指令。
怪物 if((((unsigned int)x)>>(((sizeof(int))<<3)-1)))
会比直接的慢 if(x < 0)
: 两个版本都需要将一个值与零进行比较,但是你的怪物在比较之前添加了一个移位。