我需要将数字转换为最小的log2 + 1,但我有一个问题,在32位Ruby中,log2(8)= 2.9999999999999996
输入(pos
)和输出(level
)应为:
1 -> 1
2-3 -> 2
4-7 -> 3
8-15 -> 4
16-31 -> 5
and so on..
我的公式:
pos = 8
level = ( Math.log(pos,2) + 1 ).to_i
# 3 (wrong) in 32-bit Ruby
# 4 (correct) in 64-bit Ruby
是否有更多方法可以防止这种情况发生,或者是否有其他公式将pos
转换为纠正level
,如上所示?
答案 0 :(得分:2)
pos = 8
level = 0
until pos < 2
level += 1
pos /= 2
end
level + 1 #=> 4
答案 1 :(得分:1)
这是另一种有趣的计算整数的对数的方法:
0.upto(Float::INFINITY).find{|e| x - base**e < base }
答案 2 :(得分:-1)
IEEE 754-2008 binary32
的最大可表示值为(2−2**(−23)) × 2**127
,因此存储在二进制32中的数字的base 2 log
小于十进制128.由于四舍五入错误只是一小部分,我们可以舍入到最接近的整数,看看2到整数幂是否等于给定的数字。如果是,则返回整数幂;否则返回nil
,表示它不是2的幂。
def log_2_if_integer(n)
x = Math.log(n,2).round(0).to_i
(2**x == n) ? x : nil
end
log_2_if_integer(4) #=> 2
log_2_if_integer(512) #=> 9
log_2_if_integer(3) #=> nil
换句话说,因为日志小于128,舍入错误无法产生值x
,因此任何(正或负)整数2**(x+m) == n
都会m != 0
。