将数字转换为log2

时间:2014-09-25 05:18:41

标签: ruby math floating-accuracy

我需要将数字转换为最小的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,如上所示?

3 个答案:

答案 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

相关问题