首页 > 学技术 > 技术网文 > C/C++ > 正文

[精彩] 不用四则运算,怎么实现 var = var+1 ?


来源 chinaunix.net kuqin整理

可以用位运算



 zhhui2000 回复于:2006-10-04 11:27:00

二进制中最后的0[1]*-->1[0]*


 awk就是awp加ak 回复于:2006-10-04 11:31:46

如果最后一位是1如何进位?


 win_hate 回复于:2006-10-04 11:57:07

val++


 大大狗 回复于:2006-10-04 12:54:59

引用:原帖由 win_hate 于 2006-10-4 11:57 发表
val++ 


直接了当。^_^


 langue 回复于:2006-10-04 13:16:07

回楼主:OpenSSL里对packet sequence的操作就是这样的


 awk就是awp加ak 回复于:2006-10-04 15:50:48

++也不算阿,不是加法的一种吗


 langue 回复于:2006-10-04 15:52:52

回楼上:add和incr指令是有区别的


 langue 回复于:2006-10-04 16:04:27

从OpenSSL里剽窃过来的代码:

声明:

unsigned char seq[8] = {0};

int i;


当需要加1的时候,执行:

for (i=7; i>=0; i--) {

++seq;
if (seq != 0) break; 
}


呵呵,还是64位的整数呢


 mik 回复于:2006-10-04 17:50:03

++ 运算符属于加法运算范畴, LZ 想要的是通过位运算达到加1目的。


 langue 回复于:2006-10-04 18:07:58

实现一个新的operator行么?


 mik 回复于:2006-10-04 18:34:36

实现 operator 没必要。

我算法差极,暂时还没想到方法。

00 | 01 = 01
10 | 01 = 11
11 ^ 11 = 00 (加进位)

向这个方向考虑吧


 win_hate 回复于:2006-10-04 18:37:17

1、++ 是一元运算, 而 + 是二元运算,本质的不同。

2、


unsigned int
add_one (unsigned int a)
{
unsigned i=1;
if (!(i & a))
return a | i;
else 
a=a^i;
i<<=1;

while (i & a) {
a^=i;
i<<=1;
}

return a | i;
}


[ 本帖最后由 win_hate 于 2006-10-4 18:46 编辑 ]


 awk就是awp加ak 回复于:2006-10-04 21:52:48

楼上的是最直接的实现方法。谢谢!
我应该先想想,其实思路有了,就是没有动手,呵呵!

unsigned int inc(unsigned int val){

        int off = 0;
        while (val & (1 << off)) val ^= 1 << off++;  
                
        if (off || !(val & 1)) val |= 1 << off;
        return val;
}



 emacsnw 回复于:2006-10-04 23:58:58

引用:原帖由 awk就是awp加ak 于 2006-10-4 05:52 发表
楼上的是最直接的实现方法。谢谢!
我应该先想想,其实思路有了,就是没有动手,呵呵!

unsigned int inc(unsigned int val){

        int off = 0;
        while (val & (1 << off)) v ... 



你的代码不是用了 ++ 了吗?off++ 也行的话为什么不能 val++ ?


 awk就是awp加ak 回复于:2006-10-05 09:53:35

啊。。我错了,哈哈


 awk就是awp加ak 回复于:2006-10-05 09:57:32

不过这改起来应该很简单了,用个变量替换就可以


 awk就是awp加ak 回复于:2006-10-05 10:07:13

这样了!

unsigned int inc(unsigned int val){

        int off = 1;
        while (val & off) {
                val ^= off;
                off <<= 1;
        }

        if (off == 1 || !(val & 1)) val |= 1 << (off >> 1);
        return val;
}



 awk就是awp加ak 回复于:2006-10-05 10:08:56

谢谢大家!


 awk就是awp加ak 回复于:2006-10-05 16:19:44

笨,偶发现最后一个 if 是多此一举了!
unsigned int inc(unsigned int val){


        int off = 1;
        while (val & off) {
                val ^= off;
                off <<= 1;
        }

        return val | off;
}



 langue 回复于:2006-10-05 16:31:34

引用:原帖由 awk就是awp加ak 于 2006-10-5 16:19 发表
笨,偶发现最后一个 if 是多此一举了!
unsigned int inc(unsigned int val){


        int off = 1;
        while (val & off) {
                val ^= off;
                off <<=  ... 



有“智”不在年高。鼓励一下!


 awk就是awp加ak 回复于:2006-10-05 16:42:05

如此抬举,老朽不胜感激!


 calvados 回复于:2006-10-05 20:35:07

#include <stdio.h>
int main(void)
{
    unsigned int i;
    unsigned locatebitzero=1;
    usigned int mask=0xFFFE;
    printf("input i:");
    scanf("%u",&i);
    while(i&locatebitzero){locatebitzero<<=1;mask<<=1;}
    i&=mask;i|=locatebitzero;
    printf("%u\n",i);
    retun 0;
}


 王紫豪 回复于:2006-10-05 22:22:58

哈哈,不错


 jemyzhang 回复于:2006-10-06 10:23:54

楼主,不用四则运算而用位操作的原因是什么?


 awk就是awp加ak 回复于:2006-10-06 17:40:39

只是一个奇怪的题目要求,没有实际用处


 Elite 回复于:2006-10-19 13:39:32

-var = ~var + 1,
所以
var + 1 = -(~var),
对var取反,再取其负值就得到var + 1。


 r2007 回复于:2006-10-19 13:45:34

查表算不算?
a[256]={1,2,3,...,255,0}
var=a[var]
:mrgreen:


 chzht001 回复于:2006-10-19 14:25:10

引用:原帖由 awk就是awp加ak 于 2006-10-4 10:24 发表
可以用位运算 



asm (lea var,%eax; inc (%eax); )

[ 本帖最后由 chzht001 于 2006-10-19 14:26 编辑 ]


 awk就是awp加ak 回复于:2006-10-26 15:48:20

引用:原帖由 Elite 于 2006-10-19 13:39 发表
-var = ~var + 1,
所以
var + 1 = -(~var),
对var取反,再取其负值就得到var + 1。 


妙!


 awk就是awp加ak 回复于:2006-10-26 15:49:27

引用:原帖由 r2007 于 2006-10-19 13:45 发表
查表算不算?
a[256]={1,2,3,...,255,0}
var=a[var]
:mrgreen: 


呵呵!也不错!


 meilinxiaoxue 回复于:2006-12-22 09:13:22

#include<stdio.h>

#include<stdlib.h>

int incr(int i)
{
int j = ~i ;
unsigned int k = 1, prek;

while (!(j & k))
{
prek = k;
k <<= 1;
k |= prek;
}

return (i ^ k);
}
int main(int argc, char * argv[])
{
int i; 

if (argc == 2)
{
i = atoi(argv[1]);
i = incr(i);

printf("result:%d\n", i);
}
else
{
printf("useage:command {number}\n");
}

}



 moaotian 回复于:2006-12-22 10:27:23

如果Var的原值是-1,-2,-3,-(MAX_INT+1)
和MAX_INT各位你们的算法的结果会不会很奇怪呢???????????


 rrrrrrrr8 回复于:2006-12-22 10:35:48

自己做一个CPU加法器,多此一举,反而很慢,位运算在做乖法时还可以考虑一下.


 whyglinux 回复于:2006-12-22 15:35:22

struct CharPair {

  char first;
  char second;
};

typedef int TYPE;

TYPE increase_one( TYPE var )
{
  return (TYPE)&((struct CharPair*)var)->second;
}

#include <stdio.h>

int main( void )
{
  TYPE var = 9;

  printf( "%d\n", increase_one( var ) );

  return 0;
}

只要是整数类型,并且不超出指针类型大小,正负都可以。


 Edengundam 回复于:2006-12-22 15:59:14

引用:原帖由 whyglinux 于 2006-12-22 15:35 发表
struct CharPair {

  char first;
  char second;
};

typedef int TYPE;

TYPE increase_one( TYPE var )
{
  return (TYPE)&((struct CharPair*)var)->second;
}

#include <stdio ... 




......感慨一下, 看了3分钟, 才明白, whyglinux 请让我再崇拜下:em10:

利用地址运算, 来实现 + 1....无敌了


 meilinxiaoxue 回复于:2006-12-22 16:04:15

用地址计算在语言这里模糊了“加”,编译器翻译过去是会会用到加操作.这个方法用来计算结构成员的偏移很有用好象是在windows高级编程还是matt pike的书里面看到这么用的


 whyglinux 回复于:2006-12-22 16:46:39

>> 用地址计算在语言这里模糊了“加”,编译器翻译过去是会会用到加操作

确实是这样的。但是我们只要保证了不在程序中使用 +、-、*、/、% 以及 ++、-- 等运算,就应该没有使用楼主所说的四则运算。至于编译器的实现,不是 C 程序本身能够控制的,应该不再讨论的范畴之内。


 langq235 回复于:2006-12-23 00:36:37

引用:查表算不算?
a[256]={1,2,3,...,255,0}
var=a[var]



这个太有意思了


 whyglinux 回复于:2006-12-23 11:12:42

>> 查表算不算?

var=a[var] 中 a[var] 在 C 中相当于 *(a + var),你说算不算?


 wyaccent 回复于:2006-12-23 21:21:20

引用:原帖由 Elite 于 2006-10-19 13:39 发表
-var = ~var + 1,
所以
var + 1 = -(~var),
对var取反,再取其负值就得到var + 1。 




-var难道不是 -1 * var 吗??




原文链接:http://bbs.chinaunix.net/viewthread.php?tid=837247
转载请注明作者名及原文出处



收藏本页到: