MATLAB——nextpow2函数

eg:

2^nextpow2(320)=512

2^nextpow2(128)=128

2^nextpow2(129)=256

 

y = nextpow2(x);
则2y为大于等于x的最小的二的整数次幂的数字。这样说起来似乎有些拗口,举个例子,如果x等于100,则y=7,因为27==128,而128是所有大于100的,二的整数次幂数字中最小的一个。
    对于特殊的数值,下面一一解释:
负数:  如果x<0,则nextpow2(x)等效于nextpow2(abs(x));
无穷大:如果x==inf或x==-inf,nextpow2(x)==inf
NaN:   如果x==NaN,nextpow2(x)==NaN
    如果叫我们来实现nextpow2,且不考虑上面的三类数值,那么首先想到的方法大概就是:
function y = nextpow2(x)
y = ceil(log2(x));
但是有个问题,没有考虑x为0的情况,所以稍微精炼一下:
function y = nextpow2(x)
if (x == 0)
  y = 0;
else
  y = ceil(log2(x));
end
这样应该很好了吧!
    但是实际上这并不是我首选的方法,也不是Matlab的nextpow2所选择的方法。虽然很直观,很数学。由于我曾经在FPGA上做过一些简单的浮点算法,所以对于IEEE754标准有一点了解,并写了系列笔记《探索浮点运算》。在《计算对数函数ln》中特别提到过对数的计算。通过对于754浮点数的研究,我渐渐明白,像ceil(log2(x))这样的运算,在支持754浮点类型的机器上,完全不需要使用任何算术运算,即可实现。具体的细节就不做细致的说明了,这些在《探索浮点运算》中的各篇笔记中已经反复说明过了。现在我演示一下如何在Python中完全利用位操作实现ceil(log2(x)):
import ctypes as ct

# 2011.03.29 PM 08:49
# ActivePython 2.6.6.15
# Win7 64
# xialulee

class FloatBits(ct.Structure):
    _fields_ = [
        ('M', ct.c_uint, 23),
        ('E', ct.c_uint, 8),
        ('S', ct.c_uint, 1)
    ]

class Float(ct.Union):
    _anonymous_ = ('bits', )
    _fields_ = [
        ('value',   ct.c_float),
        ('bits',    FloatBits)
    ]

def ceillog2(x):
    if x < 0:
        x = -x
    if x == 0:
        return 0
    d = Float()
    d.value = x
    if d.M == 0:
        return d.E - 127
    return d.E - 127 + 1


试试:
>>> ceillog2(100)
7L
(2的7次方等于128)
>>> ceillog2(4)
2L
(2的2次方等于4)
>>> ceillog2(1.5)
1L
(2的1次方等于2)
>>> ceillog2(0.1)
-3L
(2的-3次方等于0.125)
从上面的代码可以看出,完全使用操作位域的手法,即可实现ceil(log2(x))的操作,完全不需要任何算术运算,迭代算法什么的,有效地利用了机器的能力。
    现在再看看Matlab的nextpow2是如何实现的。nextpow2中第一行代码就使用了log2函数。(我不清楚Matlab的代码遵循什么协议,所以这里就不直接贴代码了)。但是这里的log2并不是普通的log2,而是log2函数的一种特殊形式:两个返回值的log2函数。根据文档,当log2函数具有两个返回值时:
[F,E] = log2(X)

X = F.*2.^E
其中E是整数,而0.5 <= abs(F) < 1
文档中同时提到,以这种形式使用log2时,可以联想C库中的frexp,这是用来拆分浮点数尾数和指数的函数。所以Matlab的nextpow2和我们上面的Python代码一样,并没有计算以2为底的对数函数的数值,而仅仅是将输入数值的尾数和浮点数进行了拆分。但并不是直接拆分。754规定的浮点数的尾数部分应该是大于等于1的(针对普通数值,不包括0,inf,nan这样的特殊数值),而log2函数返回的两个部分中,尾数部分则是在区间[0.5, 1)中。相对于是把754浮点数的尾数部分除以2,并将指数部分加1。
    现在将log2得到的整数的指数部分返回,那么nextpow2就完成任务了吧?其实不然。log2得到的尾数部分为0.5,则说明该数值754形式的尾数部分为2×0.5==1,尾数的小数部分为0,该数本身就是2的整数次幂,则此时应该返回log2得到的指数部分的数值减去1。例如:
>> [F, E] = log2(128)

F =

    0.5000


E =

     8
    接下来,就是处理inf和NaN的代码,没有什么好说的了。

学习自: https://blog.csdn.net/chezhai/article/details/53190085

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值