请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句
感觉比较有意思,就贴出来,如果不好,大家不要用鸡蛋砸我啊~呵呵
请定义一个宏,比较两个数a、b的大小,不能使用大于、小于、if语句
试试这个
/**
*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
上面几个程序思路都一样,只是分了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 ??
niutao@niutao-desktop:~/c$ gcc -o def def.c
niutao@niutao-desktop:~/c$ ./def
111111111 11111111
-1
--
My Bolg: http://niutao.cublog.cn
>这样写是不是会支持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.
--
My Bolg: http://niutao.cublog.cn
如果你不把浮点数看成“整数”的话,这句话没错。
可这里是C,C里面一切对象都是字节序列,当然浮点数不会例外。这里大有文章可作。
>所以别想直接用位操作来完成这个问题的浮点数版本.
很不幸,这个论断不成立,用位操作比较浮点数是可行的:
http://www.lomont.org/Math/Papers/2005/CompareFloat.pdf
--
"Sometimes the only way to stay sane is to go a little crazy."
>可这里是C,C里面一切对象都是字节序列,当然浮点数不会例外。这里大有文章可作。
我同意你的观点,但我想这种操作只能是先把浮点数的字节序列提取再进行操作。但是,直接对浮点数变量(或者更准确一点--编译器认为应该当做浮点格式来处理的字节序列)的位操作,我想不会是合法的。不仅是c里面,c++标准也是这么规定的。
>>所以别想直接用位操作来完成这个问题的浮点数版本.
>
>很不幸,这个论断不成立,用位操作比较浮点数是可行的:
>http://www.lomont.org/Math/Papers/2005/CompareFloat.pdf
谢谢你的提醒。我看了这篇文章,里面的方法很明显是将浮点数的字符序列字节提取放入整型变量中,然后对该字符序列进行操作,因为现在这些字符序列已经在整型变量中了,所以在上面执行位操作是合法的。但是我当时说前面那句话的时候特别强调了“直接”二字,即有此顾虑。我想如果我这句话前面引用的部分如果没有略去的话就可以看出来,这句话是有上下文的。当然我的表达也是存在问题的。Sorry!
不对,从二进制的角度讲所有类型都是一样的,都是字节序列,当然包括浮点数。
问题是浮点数的二进制格式(如果我们可以这么叫的话)和普通整数不一样,所以它
才需要浮点数寄存器,FPU来单独处理。但从数学的角度讲,以普通整数的方式来处理
浮点数是可行的。
>>可这里是C,C里面一切对象都是字节序列,当然浮点数不会例外。这里大有文章可作。
>我同意你的观点,但我想这种操作只能是先把浮点数的字节序列提取再进行操作。但是,直接对浮点数变量(或者更准确一点--编译器认为应该当做浮点格式来处理的字节序列)的位操作,我想不会是合法的。不仅是c里面,c++标准也是这么规定的。
C的类型已经把这限定了,C是一个强类型的语言,所以转换是必须的。
P.S.
C++会许有点儿不同,它的POD才是和C里面的类型等价的(即都是普通字节序列),
而非POD(比如class?)则是不同的。
>不对,从二进制的角度讲所有类型都是一样的,都是字节序列,当然包括浮点数。
我所说的正是二进制字节序列,格式指的也是二进制字节序列的格式。比如用整型变量存储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语言,还需练练再向您请教。