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