一道C语言题目

1 view
Skip to first unread message

李磊

unread,
Oct 10, 2008, 11:09:52 PM10/10/08
to xiyou...@googlegroups.com
感觉比较有意思,就贴出来,如果不好,大家不要用鸡蛋砸我啊~呵呵


请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句

Thomas X. Iverson

unread,
Oct 10, 2008, 11:20:29 PM10/10/08
to 李磊, xiyou...@googlegroups.com


2008/10/11 李磊 <lile...@gmail.com>

感觉比较有意思,就贴出来,如果不好,大家不要用鸡蛋砸我啊~呵呵


请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句



前面已经给李磊大哥说了一些基本的解决思想了,不一定对,各位可以看看

--
Keep It Simple Stupid

http://blog.ghostunix.org

ghosTM55

Steven Zhou

unread,
Oct 10, 2008, 11:33:08 PM10/10/08
to Thomas X. Iverson, 李磊, xiyou...@googlegroups.com
三目运算符?

2008/10/11 Thomas X. Iverson <t...@ghostunix.org>



--
Best Regards.

Wenlong Chou

unread,
Oct 11, 2008, 12:49:57 AM10/11/08
to Steven Zhou, Thomas X. Iverson, 李磊, xiyou...@googlegroups.com
/*
 *目前只能比较整数,用的是 位运算
 */
 
#include<stdio.h>
#define OUT printf("min = a\n"):printf("min = b\n")

int main(void)
{
    int a,b,c=128,d;
   
    printf("Please Input a b:\n");
    scanf("%d%d",&a,&b);
   
    d=a-b;
    d=d&c;
   
    d==128?OUT;
   
   
    return 0;   

}

2008/10/11 Steven Zhou <lulla...@gmail.com>

bianji...@gmail.com

unread,
Oct 11, 2008, 3:19:56 AM10/11/08
to Wenlong Chou, Steven Zhou, Thomas X. Iverson, 李磊, xiyou...@googlegroups.com
在 2008-10-11六的 12:49 +0800,Wenlong Chou写道:

> /*
> *目前只能比较整数,用的是 位运算
> */
>
> #include<stdio.h>
> #define OUT printf("min = a\n"):printf("min = b\n")
>
> int main(void)
> {
> int a,b,c=128,d;
>
> printf("Please Input a b:\n");
> scanf("%d%d",&a,&b);
>
> d=a-b;
> d=d&c;
>
> d==128?OUT;
>
>
> return 0;
>
> }
你这样不好吧?当a与b相差128时会是什么样子的?eg:a = 129, b = 1此时还会输
出小的数是a阿。当然了,灵活的位操作可以有效地提高程序运行的效率。

李磊

unread,
Oct 11, 2008, 3:53:25 AM10/11/08
to bianji...@gmail.com, Wenlong Chou, Steven Zhou, Thomas X. Iverson, xiyou...@googlegroups.com
2008/10/11 bianji...@gmail.com <bianji...@gmail.com>:

> 在 2008-10-11六的 12:49 +0800,Wenlong Chou写道:
>> /*
>> *目前只能比较整数,用的是 位运算
>> */
>>
>> #include<stdio.h>
>> #define OUT printf("min = a\n"):printf("min = b\n")
>>
>> int main(void)
>> {
>> int a,b,c=128,d;
>>
>> printf("Please Input a b:\n");
>> scanf("%d%d",&a,&b);
>>
>> d=a-b;
>> d=d&c;
>>
>> d==128?OUT;
>>
>>
>> return 0;
>>
>> }
> 你这样不好吧?当a与b相差128时会是什么样子的?eg:a = 129, b = 1此时还会输
> 出小的数是a阿。当然了,灵活的位操作可以有效地提高程序运行的效率。
他思路是正确的,只是考虑的不够全面。

WANG Tinggong

unread,
Oct 11, 2008, 4:16:52 AM10/11/08
to 李磊, bianji...@gmail.com, Wenlong Chou, Steven Zhou, Thomas X. Iverson, xiyou...@googlegroups.com

试试这个
/**
*a<b 返回 -1
*a==b 返回 0
*a>b 返回 1
*/
#define CMP(a, b) ((a)-(b)?((long)((a)-(b))&0x80000000?-1:1):0)


--
attitude is all

李磊

unread,
Oct 11, 2008, 4:25:41 AM10/11/08
to WANG Tinggong, bianji...@gmail.com, Wenlong Chou, Steven Zhou, Thomas X. Iverson, xiyou...@googlegroups.com
>
> 试试这个
> /**
> *a<b 返回 -1
> *a==b 返回 0
> *a>b 返回 1
> */
> #define CMP(a, b) ((a)-(b)?((long)((a)-(b))&0x80000000?-1:1):0)
同意。我没考虑等于的情况。。。
#define PRINT(a) printf("%ld",a)
#define max(a,b) ((((long)((a)-(b)))&0x80000000)?PRINT(b):PRINT(a))

Chen Fengyang

unread,
Oct 11, 2008, 4:28:58 AM10/11/08
to WANG Tinggong, xiyou...@googlegroups.com
On Sat, Oct 11, 2008 at 04:16:52PM +0800, WANG Tinggong wrote:
>Date: Sat, 11 Oct 2008 16:16:52 +0800
>From: WANG Tinggong <wangti...@gmail.com>
>Subject: [XiYouLinux] Re: 一道C语言题目
>To: 李磊 <lile...@gmail.com>
>CC: "bianji...@gmail.com" <bianji...@gmail.com>,
> Wenlong Chou <wenlon...@gmail.com>,
> Steven Zhou <lulla...@gmail.com>,
> "Thomas X. Iverson" <t...@ghostunix.org>,
> xiyou...@googlegroups.com

上面几个程序思路都一样,只是分了16位版本和32位版本。都是通过验证a-b得出的最高位是1还是0得出大小。第一个版本只能在TC2.0那样的16位编译器下才是正确的哦,32位编译器下出来的就~~了。后面这个是32位版本的,而且明显考虑周到:-)

>>

李则良

unread,
Oct 11, 2008, 4:35:04 AM10/11/08
to WANG Tinggong, xiyou...@googlegroups.com
2008/10/11 Chen Fengyang <blueblue...@gmail.com>:
不错!
不过这个仅仅支持整形的!

#define CMP(a, b) ((a)-(b)?((long)((a)-(b))&0x80000000?-1:1):0)
例如:
#include <stdio.h>

#define CMP(a, b) ((a)-(b)?((long)((a)-(b))&0x80000000?-1:1):0)
int main()
{
float a,b;
scanf("%f%f",&a,&b);
printf("%d\n",CMP(a,b));
return 0;
}
运行结果:
lzel@lzel-desktop:~/works/proc$ ./a.out
12.2 12.3
1
lzel@lzel-desktop:~/works/proc$ ./a.out
12.3 12.2
1
lzel@lzel-desktop:~/works/proc$ ./a.out
12.2 12.2
0
不过,已经很不错了。
>
>>>
>
> >
>

Chen Fengyang

unread,
Oct 11, 2008, 5:42:49 AM10/11/08
to 李则良, WANG Tinggong, xiyou...@googlegroups.com
On Sat, Oct 11, 2008 at 04:35:04PM +0800, 李则良 wrote:
<snip>

>> 上面几个程序思路都一样,只是分了16位版本和32位版本。都是通过验证a-b得出的最高位是1还是0得出大小。第一个版本只能在TC2.0那样的16位编译器下才是正确的哦,32位编译器下出来的就~~了。后面这个是32位版本的,而且明显考虑周到:-)
>不错!
>不过这个仅仅支持整形的!

no,不支持无符号整形,比如 unsigned int unsigned long

>#define CMP(a, b) ((a)-(b)?((long)((a)-(b))&0x80000000?-1:1):0)
>例如:
>#include <stdio.h>
>#define CMP(a, b) ((a)-(b)?((long)((a)-(b))&0x80000000?-1:1):0)
>int main()
>{
> float a,b;

位运算符不能作用于浮点数!!!所以别想直接用位操作来完成这个问题的浮点数版本.
C99 P67 6.5
Some operators (the unary operator ˜, and the binary operators <<, >>, &, ˆ, and |,
collectively described as bitwise operators) are required to have operands that have
integer type. These operators return values that depend on the internal representations of
integers, and have implementation-defined and undefined aspects for signed types.

而且你的程序中a,b均为float型,又在宏里面将它们的差(也是float型)强制转换为long ??

李则良

unread,
Oct 11, 2008, 7:27:09 AM10/11/08
to 李则良, WANG Tinggong, xiyou...@googlegroups.com
2008/10/11 Chen Fengyang <blueblue...@gmail.com>:

> On Sat, Oct 11, 2008 at 04:35:04PM +0800, 李则良 wrote:
> <snip>
>>> 上面几个程序思路都一样,只是分了16位版本和32位版本。都是通过验证a-b得出的最高位是1还是0得出大小。第一个版本只能在TC2.0那样的16位编译器下才是正确的哦,32位编译器下出来的就~~了。后面这个是32位版本的,而且明显考虑周到:-)
>>不错!
>>不过这个仅仅支持整形的!
>
> no,不支持无符号整形,比如 unsigned int unsigned long
>
>>#define CMP(a, b) ((a)-(b)?((long)((a)-(b))&0x80000000?-1:1):0)
>>例如:
>>#include <stdio.h>
>>#define CMP(a, b) ((a)-(b)?((long)((a)-(b))&0x80000000?-1:1):0)
>>int main()
>>{
>> float a,b;
> 位运算符不能作用于浮点数!!!所以别想直接用位操作来完成这个问题的浮点数版本.
> C99 P67 6.5
> Some operators (the unary operator ˜, and the binary operators <<, >>, &, ˆ, and |,
> collectively described as bitwise operators) are required to have operands that have
> integer type. These operators return values that depend on the internal representations of
> integers, and have implementation-defined and undefined aspects for signed types.
俄,这个我还真不知道,学习了

More

unread,
Oct 11, 2008, 8:07:19 AM10/11/08
to 西邮Linux兴趣小组
学习了

Wenlong Chou

unread,
Oct 11, 2008, 10:25:11 AM10/11/08
to More, 西邮Linux兴趣小组
  看了这么多,真的是考虑不周啊,学了很多 ^_^

2008/10/11 More <mo...@21cn.com>
学习了


Niu Tao

unread,
Oct 11, 2008, 8:44:53 PM10/11/08
to Wenlong Chou, More, 西邮Linux兴趣小组
2008/10/11 Wenlong Chou <wenlon...@gmail.com>:

> 看了这么多,真的是考虑不周啊,学了很多 ^_^
>
> 2008/10/11 More <mo...@21cn.com>
>>
>> 学习了
>>
>
这样写是不是会支持32位和16位,并且支持向long long这样的类型:
#include<stdio.h>
#define CMP(a,b,type) ({ \
typeof(type) max=1<<sizeof(type); \
((a)-(b)?((type)((a)-(b))&max?-1:1):0); \
})
int main()
{
long long a,b;
int flags;
scanf("%ld%ld",&a,&b);
flags=CMP(a,b,long long);
printf("%d\n",flags);
return 0;
}

niutao@niutao-desktop:~/c$ gcc -o def def.c
niutao@niutao-desktop:~/c$ ./def
111111111 11111111
-1

--
My Bolg: http://niutao.cublog.cn

Chen Fengyang

unread,
Oct 12, 2008, 2:47:04 AM10/12/08
to Niu Tao, Wenlong Chou, More, 西邮Linux兴趣小组
On Sun, Oct 12, 2008 at 08:44:53AM +0800, Niu Tao wrote:

>这样写是不是会支持32位和16位,并且支持向long long这样的类型:
>#include<stdio.h>
>#define CMP(a,b,type) ({ \
> typeof(type) max=1<<sizeof(type); \

sizeof 操作符得到的是其操作数在字节级别上的大小,也就是有多少个字节,返回无符号整型数(size_t).
所以1<<sizeof(type)里面的type如果是long long的话,那么上面的1只是向左移了8bit,而非设想的8bytes(32bits)。就算是移动了32位,也有问题,应该是31位。
K&R p204 A7.4.8 Sizeof Operator:
The sizeof operator yields the number of bytes required to store an object of the type of its operand. The operand is either an expression, which is not evaluated, or a parenthesized type name.

C99 p209 6.5.3.4 The sizeof operator
The sizeof operator yields the size (in bytes) of its operand, which may be an
expression or the parenthesized name of a type.

Niu Tao

unread,
Oct 12, 2008, 3:34:24 AM10/12/08
to Niu Tao, Wenlong Chou, More, 西邮Linux兴趣小组
On Sun, Oct 12, 2008 at 2:47 PM, Chen Fengyang
<blueblue...@gmail.com> wrote:
> On Sun, Oct 12, 2008 at 08:44:53AM +0800, Niu Tao wrote:
>
>>这样写是不是会支持32位和16位,并且支持向long long这样的类型:
>>#include<stdio.h>
>>#define CMP(a,b,type) ({ \
>> typeof(type) max=1<<sizeof(type); \
> sizeof 操作符得到的是其操作数在字节级别上的大小,也就是有多少个字节,返回无符号整型数(size_t).
> 所以1<<sizeof(type)里面的type如果是long long的话,那么上面的1只是向左移了8bit,而非设想的8bytes(32bits)。就算是移动了32位,也有问题,应该是31位。
的确,是我没仔细看。

> K&R p204 A7.4.8 Sizeof Operator:
> The sizeof operator yields the number of bytes required to store an object of the type of its operand. The operand is either an expression, which is not evaluated, or a parenthesized type name.
>
> C99 p209 6.5.3.4 The sizeof operator
> The sizeof operator yields the size (in bytes) of its operand, which may be an
> expression or the parenthesized name of a type.
>
>> ((a)-(b)?((type)((a)-(b))&max?-1:1):0); \
>>})
>>int main()
>>{
>> long long a,b;
>> int flags;
>> scanf("%ld%ld",&a,&b);
>> flags=CMP(a,b,long long);
>> printf("%d\n",flags);
>> return 0;
>>}
>>
>>niutao@niutao-desktop:~/c$ gcc -o def def.c
>>niutao@niutao-desktop:~/c$ ./def
>>111111111 11111111
>>-1
>

--
My Bolg: http://niutao.cublog.cn

proram...@gmail.com

unread,
Oct 12, 2008, 8:14:45 AM10/12/08
to 西邮Linux兴趣小组
关于浮点数 其实可以使用函数ecvt的到a-b的符号
#include "stdlib.h"
#include "stdio.h"
#include "conio.h"
main()
{
float a,b;
int sign=0;
scanf("%f %f",&a,&b);
a==b?printf("=\n"):(ecvt(a-b,0,0,&sign),printf("%d\n",sign));

feeling4t feeling4t

unread,
Oct 14, 2008, 9:50:51 AM10/14/08
to 李磊, xiyou...@googlegroups.com
C里面还有宏???

2008/10/11 李磊 <lile...@gmail.com>

刘洋

unread,
Oct 14, 2008, 7:11:52 PM10/14/08
to feeling4t feeling4t, 李磊, xiyou...@googlegroups.com
On Tue, Oct 14, 2008 at 09:50:51PM +0800, feeling4t feeling4t wrote:
> C里面还有宏???
>
我很无语~你不要说你只知道M$ Office里有宏~

李磊

unread,
Oct 14, 2008, 7:22:09 PM10/14/08
to feeling4t feeling4t, 李磊, xiyou...@googlegroups.com
2008/10/15 刘洋 <yang....@gmail.com>:

> On Tue, Oct 14, 2008 at 09:50:51PM +0800, feeling4t feeling4t wrote:
>> C里面还有宏???
>>
> 我很无语~你不要说你只知道M$ Office里有宏~
老大也被雷到了。。。
昨天wangcong那个视频把我雷的够呛阿~哈哈

More

unread,
Oct 15, 2008, 12:36:23 AM10/15/08
to 西邮Linux兴趣小组
哈哈哈哈 哈哈哈哈 哈哈哈哈

On Oct 14, 9:50 pm, "feeling4t feeling4t" <feelin...@gmail.com> wrote:
> C里面还有宏???
>
> 2008/10/11 李磊 <lilei1...@gmail.com>

Américo Wang

unread,
Oct 16, 2008, 1:00:15 PM10/16/08
to 李则良, WANG Tinggong, xiyou...@googlegroups.com
On Sat, Oct 11, 2008 at 05:42:49PM +0800, Chen Fengyang wrote:
>位运算符不能作用于浮点数!!!

如果你不把浮点数看成“整数”的话,这句话没错。
可这里是C,C里面一切对象都是字节序列,当然浮点数不会例外。这里大有文章可作。


>所以别想直接用位操作来完成这个问题的浮点数版本.

很不幸,这个论断不成立,用位操作比较浮点数是可行的:
http://www.lomont.org/Math/Papers/2005/CompareFloat.pdf


--
"Sometimes the only way to stay sane is to go a little crazy."

Chen Fengyang

unread,
Oct 17, 2008, 6:32:06 AM10/17/08
to Américo Wang, 李则良, WANG Tinggong, xiyou...@googlegroups.com
On Thu, Oct 16, 2008 at 06:00:15PM +0100, Américo Wang wrote:
>Date: Thu, 16 Oct 2008 18:00:15 +0100
>From: Américo Wang <xiyou.w...@gmail.com>
>Subject: [XiYouLinux] Re: 一道C语言题目
>To: 李则良 <lizelia...@gmail.com>,
> WANG Tinggong <wangti...@gmail.com>, xiyou...@googlegroups.com

>
>On Sat, Oct 11, 2008 at 05:42:49PM +0800, Chen Fengyang wrote:
>>位运算符不能作用于浮点数!!!
>
>如果你不把浮点数看成“整数”的话,这句话没错。
我不大明白你的意思。一个整数可以以普通整型的格式存储,也可以以浮点数格式存储(当然,单纯从数学角度看,它依然是一个整数,但是计算机把它当成浮点数按照浮点格式来处理)。我这样的理解对吗?能否再解释一下你的意思。

>可这里是C,C里面一切对象都是字节序列,当然浮点数不会例外。这里大有文章可作。
我同意你的观点,但我想这种操作只能是先把浮点数的字节序列提取再进行操作。但是,直接对浮点数变量(或者更准确一点--编译器认为应该当做浮点格式来处理的字节序列)的位操作,我想不会是合法的。不仅是c里面,c++标准也是这么规定的。


>>所以别想直接用位操作来完成这个问题的浮点数版本.
>
>很不幸,这个论断不成立,用位操作比较浮点数是可行的:
>http://www.lomont.org/Math/Papers/2005/CompareFloat.pdf

谢谢你的提醒。我看了这篇文章,里面的方法很明显是将浮点数的字符序列字节提取放入整型变量中,然后对该字符序列进行操作,因为现在这些字符序列已经在整型变量中了,所以在上面执行位操作是合法的。但是我当时说前面那句话的时候特别强调了“直接”二字,即有此顾虑。我想如果我这句话前面引用的部分如果没有略去的话就可以看出来,这句话是有上下文的。当然我的表达也是存在问题的。Sorry!

yu zhou

unread,
Oct 17, 2008, 6:47:18 AM10/17/08
to Américo Wang, 李则良, WANG Tinggong, xiyou...@googlegroups.com
呵呵,学习了,以前以为位运算在编制普通软件的时候就那几种用法,没想到还是很灵活的!

2008/10/17 Chen Fengyang <blueblue...@gmail.com>

Américo Wang

unread,
Oct 17, 2008, 6:47:45 AM10/17/08
to Américo Wang, 李则良, WANG Tinggong, xiyou...@googlegroups.com
On Fri, Oct 17, 2008 at 06:32:06PM +0800, Chen Fengyang wrote:
>On Thu, Oct 16, 2008 at 06:00:15PM +0100, Américo Wang wrote:
>>Date: Thu, 16 Oct 2008 18:00:15 +0100
>>From: Américo Wang <xiyou.w...@gmail.com>
>>Subject: [XiYouLinux] Re: 一道C语言题目
>>To: 李则良 <lizelia...@gmail.com>,
>> WANG Tinggong <wangti...@gmail.com>, xiyou...@googlegroups.com
>>
>>On Sat, Oct 11, 2008 at 05:42:49PM +0800, Chen Fengyang wrote:
>>>位运算符不能作用于浮点数!!!
>>
>>如果你不把浮点数看成“整数”的话,这句话没错。
>我不大明白你的意思。一个整数可以以普通整型的格式存储,也可以以浮点数格式存储(当然,单纯从数学角度看,它依然是一个整数,但是计算机把它当成浮点数按照浮点格式来处理)。我这样的理解对吗?能否再解释一下你的意思。
>


不对,从二进制的角度讲所有类型都是一样的,都是字节序列,当然包括浮点数。

问题是浮点数的二进制格式(如果我们可以这么叫的话)和普通整数不一样,所以它
才需要浮点数寄存器,FPU来单独处理。但从数学的角度讲,以普通整数的方式来处理
浮点数是可行的。


>>可这里是C,C里面一切对象都是字节序列,当然浮点数不会例外。这里大有文章可作。
>我同意你的观点,但我想这种操作只能是先把浮点数的字节序列提取再进行操作。但是,直接对浮点数变量(或者更准确一点--编译器认为应该当做浮点格式来处理的字节序列)的位操作,我想不会是合法的。不仅是c里面,c++标准也是这么规定的。

C的类型已经把这限定了,C是一个强类型的语言,所以转换是必须的。


P.S.
C++会许有点儿不同,它的POD才是和C里面的类型等价的(即都是普通字节序列),
而非POD(比如class?)则是不同的。

Chen Fengyang

unread,
Oct 17, 2008, 7:37:24 AM10/17/08
to Américo Wang, 李则良, WANG Tinggong, xiyou...@googlegroups.com
On Fri, Oct 17, 2008 at 11:47:45AM +0100, Américo Wang wrote:
>>>>位运算符不能作用于浮点数!!!
>>>
>>>如果你不把浮点数看成“整数”的话,这句话没错。
>>我不大明白你的意思。一个整数可以以普通整型的格式存储,也可以以浮点数格式存储(当然,单纯从数学角度看,它依然是一个整数,但是计算机把它当成浮点数按照浮点格式来处理)。我这样的理解对吗?能否再解释一下你的意思。

>不对,从二进制的角度讲所有类型都是一样的,都是字节序列,当然包括浮点数。
我所说的正是二进制字节序列,格式指的也是二进制字节序列的格式。比如用整型变量存储3和担惊都浮点变量存储3.最终二者的二进制虽然都是32位,但是明显是不同的字符序列。
整型是 0000 0000 0000 0000 0000 0000 0000 0011
浮点是 0 00000010 10000000000000000000000

>问题是浮点数的二进制格式(如果我们可以这么叫的话)和普通整数不一样,所以它
>才需要浮点数寄存器,FPU来单独处理。但从数学的角度讲,以普通整数的方式来处理
>浮点数是可行的。

嗯,我明白你的意思了,可能这些东西说出来有点绕,一会计算机一会又纯数学的。但是我想我们的想法应该没什么不同。Thanks!


>
>>>可这里是C,C里面一切对象都是字节序列,当然浮点数不会例外。这里大有文章可作。
>>我同意你的观点,但我想这种操作只能是先把浮点数的字节序列提取再进行操作。但是,直接对浮点数变量(或者更准确一点--编译器认为应该当做浮点格式来处理的字节序列)的位操作,我想不会是合法的。不仅是c里面,c++标准也是这么规定的。
>
>C的类型已经把这限定了,C是一个强类型的语言,所以转换是必须的。

>
>
>P.S.
>C++会许有点儿不同,它的POD才是和C里面的类型等价的(即都是普通字节序列),
>而非POD(比如class?)则是不同的。

不熟悉C语言,还需练练再向您请教。

Reply all
Reply to author
Forward
0 new messages