第一步是怎么如何去掉对数符号号的?

不变,未知数系数为负数,化为一要变号

具体的还需要计算,或做图看出

就我图片上的不等式,是化对的吗

一句话的事,你就看左边的表达式是增函数就不变,减函数就变

这样的方程,需要左右同时取对数,这个过程实际上是将不等号左右两边的数值代入对数函数解析式里,比较代入后函数值的大小,这时就要注意函数的增减性。

很详细的回答!!只是我的问题已经被解答了,谢谢你
}

写者按:这篇文章原计划写成的一篇翻译,但因原文除了bit位操作技巧还花费不少笔墨记录了发现者与修订者,本文不含上述内容,只注重bit相关的操作技巧,对这些代码作者感兴趣的请移步观看。

在统计总操作数时,任何一个c语句认为是一个操作。间接赋值语句因其不用写入内存,认为其占0个操作数。当然,操作总数只是近似表示真实的计算机指令数和操作时间。本文假定所有的操作花费的时间相同,虽然实际上是不可能的,但在CPUs速度快速增长的今天,其中的差距已经非常小了。一段样例代码的执行时间还和系统的缓存大小、内存带宽、指令集等有关。实际测试是考较一段代码效率的最终手段,以下代码执行结果以你机子实际测试结果为准。

// 或者,避免分支判断的方法如下: // 或者,更少的操作数但是可移植行较差的方法:

上述代码的最后一个表达式用sign = v >> 31计算一个32位整型的符号。这步操作会比直观的sign = -(v < 0)更快。该方法之所以行的通是因为,符号整型右移时,最左的符号位会向右填充。负整型最左符号位为1, 0和正整型符号为则为0;所有位为1表示-1(补码表示法)。不幸的是,该方法只适用与特定的架构。

或者,你可能希望结果表示成-1或+1,那么可以用:

又或者,你希望结果表示成-1、0或+1,那么用:

// 或者,更快但可移植性较差的版本: // 或者,更简短直观且可移植行较好的版本:

如果你想要知道某数是否为非负数,用+1表示非负数,0表示负数,可以用:

警告: 1989 ANSI C specification 不再定义符号右移操作的结果,在某些系统上上述涉及右移操作的方法可能无效。

判断两个整型是否符号相反

int x, y; // 输入,判断这两个数符号是否相反
 

求整型的绝对值(abs, 无分支判断)

 
// 相同效果的变式:
 
某些CPU没有求整型绝对值的指令(或者编译器没使用它)。在某些机器上分支判断操作可能是比较昂贵的,上述表达式比简单方法r = (v < 0) ? -(unsigned)v : v要快,即使它们的操作数是相同的。

求两个整型的最大最小值(无分支判断)

 
在某些机器上分支判断操作可能是比较昂贵的,上式比简单方法r = (x < y) ? x : y要快,即使上式多了2个操作。(当然,一般来说最好使用简单方法,易于理解。)上式的原理是:如果x<y,那么-(x-y)全是1,所以r = y ^ (x ^ y) & ~0 = y ^ x ^ y


判断一个整型是否是2的幂

 
 
上式会错误地将0认为是2的幂,为了修正这点,使用:

 
ints)符号扩展是自动完成的,但假设你有一个有符号使用b位补码表示的数字x,想将之强转成一个int。如果x是正数,简单拷贝即可,但如果是负数,符号位必须调整到最高位。举个例子,我们用4位表示-3是1101。如果用8位表示-3则是。可以看到左边多出的4位使用了符号位填充,即符号扩展。在C中,将定长类型进行符号扩展是很简单的。如下式子将一个5bits扩展成一个整型:
以下C++模板函数使用相同的方式将B bits的转化成类型T。

// 或者,对于超标量CPUs
 
对于某些架构,无需分支判断的版本能弥补多出的操作数。在非正式速度测试中,在AMD Athlon? XP 2100+上上式快5-10%。第二个式子在Intel Core 2 Duo 超标量版本中比第一个式子要快16%。

 
如果你想仅当某flag为false是将某数取反,可以使用以下方法避免分支判断:
如果你想仅当flag为true时取反,那么使用:

 
上式比注释中的简单方法少了一个操作,但如果mask是常量的话,上式将不具优势。

统计bits数(简单方法)

 
 
简单法每个bit循环一次,对于最高位为1的32-bit的字,将循环32次。

// 或者用一下语句初始化查询表:
 

 

 
数组B中的数字用2进制表示是:

对于更大的整型,我们只需扩展B和S数组。对于k bits,S数组与B数组长度为ceil(lg(k))。(此处lg是以2为底的对数函数,下同,写者注)

统计32-bit字bits数最好的方法是下式:

根据类型T可以将上述方法参数化(对128及以内长度类型都适用):

上式是统计bits数最好的方法,操作数和查表法相同,但无需额外的内存开销。见了解更多详情,该法也称为sideways addition。

求总bits数的奇偶性

求总bits数的奇偶性(查表法)

求总bits数的奇偶性(取余法)

上式仅有4个操作,仅对bytes有效。

求总bits数的奇偶性(并行法)

上式仅约9个操作,适用于32字。对一个字节可以进行一些优化(删除2,3行)。上式中的0x6996是4-bits奇偶性查找表,移位后第0位即是奇偶性的值。

交换bits(异或方式)方法

反转bits(简单方法)

方法1需要17个操作,方法2只需12个。(假定你的CPU存取byte无须额外操作)

下边展示了该方法是如何作用的,用a,b,c,d,e,f,g,h来表示一个字节的8个位。第一步乘法展开了b的多个副本,后一个乘法将它们整合到右数第5个字节。

求余数(不用取余操作)

大部分的程序员都知道这个技巧,从完备性角度考虑还是加上它。

求以2为底的对数(简单方法)

求一个整型以2为底的对数等价与求最高位的1(MSB)。

求以2为底的对数(查表法)

对于32-bit数,查表法仅需7个操作。扩展到64-bit,将要9个操作。如果使用4个查找表可以节省1个操作。

以下方法适用于均匀分布的v,如果输入的v值中1是均匀分布的,考虑使用一下方法替代:

可以用以下方式生成查找表:

求尾部连续0的个数(并行法)

我们先分离最低位的1,c初始化为最大的32,然后逐步递减c的值。对于N bit数,平均操作数约等于3 * lg(N) + 4。

求尾部连续0的个数(2分查找法)

// 对奇数的快速处理,假定奇数占输入的1/2

该方法类似与上一个方法,但是是以积累的方式计算c。它先检测v最低的16bits是否为0, 如果都为0,将v右移16位,c加上16。后续操作每次减半直到为1为止。这个方法比上个方法大约要快33%,因为有些分支不会被执行。

向上取2的幂(浮点法)

上式等价于1U << (lg(v-1) + 1)。注意上式在v为0时返回0,该值不是2的幂。你可以在最后加上v += (v==0)来修正这结果。该方法比用查表法求v以2为底的对数法要少两个操作数,且可移植行更好。该方法将最高位的1拷贝到所有较低的bits,然后加1,进位后所有的低位变成了0,最高位上一位则变成1。如果v原本是2的幂,会先减1再向上取到原值。

交错和并bits(简单方法)

交错bits(也叫 )在线性2D整型坐标中非常有用,x和y的值被和并到一个数中,Morton Number之差越小表示两点间的x和y越接近。

交错和并bits(查表法)

如果用一个额外的表存储y的查找表可以减少一个移位操作,但是会需要额外的内存。同理,如果使用4个查找表表示上述4行的结果可以将操作数减少至11个。

交错和并bits(使用神奇的2进制数)

递推求下一个bit排列

假设我们有N bits为 1的一个整型,我们想求下一个(大于该数)满足有N bits 为 1 的整型排列。例如,如果N为3,当前整型为,下一个则是100, 等等。下面是求该排列的快速方法:

内建的__builtin_ctz(v) 函数在GNU C编译器(x86)中返回该数尾部的0 bits 的个数,如果你用微软的编译器,可以使用_BitScanForward方法。如果没有的话,可以使用前面提到求尾部连续0 bits的个数的方法。
下面另有一个使用了除法稍慢的方法,但是不用计算尾部0 bits的个数。

}

我要回帖

更多关于 怎么去掉对数符号 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信