Math 如何在没有浮点运算或长整数计算的情况下计算floor(log2(5**x))

Math 如何在没有浮点运算或长整数计算的情况下计算floor(log2(5**x)),math,floating-point,Math,Floating Point,问题是,在没有浮点运算或长整数计算的情况下,我们如何计算floor(log2(5^x))的整数值?我在寻找一种简单、高效、数学上优雅的方法 意见: 公式仅为5**x(加1)中的位数 尝试: 我试图将其简化为: 楼层(x*log2(5)) 在我的用例中,x不是非常大,可能只有1-100。虽然一个适用于小值的优雅公式就足够了,但我对一个适用于任意x值的公式/算法感兴趣 我正在做一个通用数字(III型)的参考软件实现。我想通过纯粹使用位操作和基本操作,使所有内容都可以轻松地转换为微码。这是我需要简化的

问题是,在没有浮点运算或长整数计算的情况下,我们如何计算floor(log2(5^x))的整数值?我在寻找一种简单、高效、数学上优雅的方法

意见: 公式仅为5**x(加1)中的位数

尝试: 我试图将其简化为: 楼层(x*log2(5))

在我的用例中,x不是非常大,可能只有1-100。虽然一个适用于小值的优雅公式就足够了,但我对一个适用于任意x值的公式/算法感兴趣


我正在做一个通用数字(III型)的参考软件实现。我想通过纯粹使用位操作和基本操作,使所有内容都可以轻松地转换为微码。这是我需要简化的公式之一。

正如您正确指出的,
log2(5**x)=x*log2(5)
log2(5)
是一个常数,可以近似为
2.3219281

但是,根据问题,不允许浮动。不是问题

log2_5 = 23219281;
scale = 10000000; // note log2_5/scale is the actual value
result = x * log2_5;
output = (result - (result % scale)) / scale;

通过将
result
减少
result%scale
,将其除以
scale
将是一个整数除法,而不是浮点。

正如您正确指出的,
log2(5**x)=x*log2(5)
log2(5)
是一个常数,可以近似为
2.3219281

但是,根据问题,不允许浮动。不是问题

log2_5 = 23219281;
scale = 10000000; // note log2_5/scale is the actual value
result = x * log2_5;
output = (result - (result % scale)) / scale;

通过将
result
减少
result%scale
,将其除以
scale
将是一个整数除法,而不是浮点数。

这里是一个非常粗略的近似值,但如果您想从心理上获得它,它会有所帮助

5^3 = 125
2^7 = 128
因此,对于提高到n的幂:

5^n ~~ 2^(7n/3)
因此,5^12接近2^28可能需要多达29位

这有点高估了,因为2^7>5^3,所以28位就足够了,一个很好的用法是简单地将分数上舍入

如果我在Smalltalk中进行评估:

(1 to: 50) reject: [:i | (5 raisedTo: i) highBit = (i*7/3) ceiling].
我得到:

#(31 34 37 40 43 46 49)

你可以看到,这个非常简单的公式可以工作到5^30,这并不坏。

这里是一个非常粗略的近似值,但是如果你想从心理上获得它,它会有所帮助

5^3 = 125
2^7 = 128
因此,对于提高到n的幂:

5^n ~~ 2^(7n/3)
因此,5^12接近2^28可能需要多达29位

这有点高估了,因为2^7>5^3,所以28位就足够了,一个很好的用法是简单地将分数上舍入

如果我在Smalltalk中进行评估:

(1 to: 50) reject: [:i | (5 raisedTo: i) highBit = (i*7/3) ceiling].
我得到:

#(31 34 37 40 43 46 49)
你看,非常简单的公式可以工作到5^30,这并不坏

对于一个简单,有效和数学上优雅的方式<代码>楼层(x*log2(5))

由于
x
的整数值为1到100,因此可以进行各种测试,以找到使用整数乘法和除以幂2的“最佳”值。
f(x)=x*一个整数除以2的幂

为了
f(x)=地板(x*log2(5))=地板(x*some\u float\u c)
some\u float\u c的值由以下100个最小值和最大值限定

x   f(x)    mn  mx
        f(x)/x  (f(x) + 1)/x
1   2   2.00000 3.00000
2   4   2.00000 2.50000
3   6   2.00000 2.33333
... 
59  136 2.30508 2.32203
... 
87  202 2.32184 2.33333
... 
98  227 2.31633 2.32653
99  229 2.31313 2.32323
100 232 2.32000 2.33000
最大最小值为
2.32184
,最小最大值为
2.32203

2.32184... <= some_float_c < 2.32203...
因此
9511/4096
是“最简单”的,也是“最佳”的候选者

f(x) = (x*9511) integer_divide_by_power_of_2 4096

// In C
unsigned y = (x*9511u) >> 12;
对于一个简单,有效和数学上优雅的方式<代码>楼层(x*log2(5))

由于
x
的整数值为1到100,因此可以进行各种测试,以找到使用整数乘法和除以幂2的“最佳”值。
f(x)=x*一个整数除以2的幂

为了
f(x)=地板(x*log2(5))=地板(x*some\u float\u c)
some\u float\u c的值由以下100个最小值和最大值限定

x   f(x)    mn  mx
        f(x)/x  (f(x) + 1)/x
1   2   2.00000 3.00000
2   4   2.00000 2.50000
3   6   2.00000 2.33333
... 
59  136 2.30508 2.32203
... 
87  202 2.32184 2.33333
... 
98  227 2.31633 2.32653
99  229 2.31313 2.32323
100 232 2.32000 2.33000
最大最小值为
2.32184
,最小最大值为
2.32203

2.32184... <= some_float_c < 2.32203...
因此
9511/4096
是“最简单”的,也是“最佳”的候选者

f(x) = (x*9511) integer_divide_by_power_of_2 4096

// In C
unsigned y = (x*9511u) >> 12;

5x中的位数是上限(x*log2(5)),而不是下限。你需要3位来存储51。我想它是floor(x*log2(5))+1。让我核实一下。编辑:是的,看起来我是对的。f(2)=f(3)在我们使用floor然后添加1时起作用,但对ceil不起作用。我认为你是对的。4需要3位来存储。对于大小有限的情况,您可以使用具有长整数算法的系统来计算表吗?对于[1,n]中的每个整数n,计算5,x的最小整数幂,使得2n不大于5x。存储x和n之间的映射。是的,对于x,5x中的位数是上限(x*log2(5)),而不是下限。你需要3位来存储51。我想它是floor(x*log2(5))+1。让我核实一下。编辑:是的,看起来我是对的。f(2)=f(3)在我们使用floor然后添加1时起作用,但对ceil不起作用。我认为你是对的。4需要3位来存储。对于大小有限的情况,您可以使用具有长整数算法的系统来计算表吗?对于[1,n]中的每个整数n,计算5,x的最小整数幂,使得2n不大于5x。存储x和n之间的映射。是的,使用x作为备选方案,您可以只执行
output=result intdiv scale
其中
intdiv
是带截断的整数除法,因为这也将处理您的
floor
要求。是的,这也是必要的,因为我不能使用浮点运算作为备选方案,你可以只做
output=result intdiv scale
其中
intdiv
是带截断的整数除法,因为这也将处理你的
floor
要求。是的,这也是必要的,因为我不能使用浮点运算