我想找到整数n
的对数的向上舍入值到整数基b
。在代码中:
result = int(ceil(log(n, b)))
问题在于,有时值无法在浮点中精确表示,过高估计结果。例如:
log(125, 5) == int(ceil(3.0000000000000004)) == 4
我该怎么办?减去微小的epsilon会在其他地方低估它。有没有办法完全支持浮点计算,有点像使用base 2?
我可以使用循环来找到对数,但我想知道是否可以在恒定时间内完成此操作。
答案 0 :(得分:1)
嗯,你必须要小心恒定时间的意思。如果你正在处理固定宽度的整数,那么一个简单的for循环是有界的(基数2中64位整数的最坏情况将是64次乘法)并且可能仍然比转换为float更快,调用{ {1}}函数,并截断回一个整数。
如果你使用任意精度整数,那么基本上没有恒定时间算法,因为几乎每个操作都至少为O(log(n)),包括转换为浮点数。
也就是说,还有其他一些事情可以尝试:
您可以使用find first set操作来查找base-2对数(尽管我认为Python不提供这样的功能)。 x86为此提供了bsr指令。这也是关于任意精度整数的少数操作之一,可以是恒定时间(尽管这取决于实现,内存存储等)。
一旦你有一个base-2对数,你就可以用它来计算整数除法的2次幂。
如果你只使用相同的基数b,并且输入受b k 的限制,你可以使用b的幂与二进制搜索相结合的预先计算查找表,任意精度整数都是O(log(k)* log(n))(搜索的log(k),每个不等式比较的log(n))。
即使不是这种情况,你仍然可以尝试某种二分法搜索:通过平方直到太大来保持指数加倍,然后从那里进行二分搜索。
您最初的想法,加上一些错误分析,可以快速计算某些情况,然后您可以回到不精确的情况。 Python没有为2参数log
提供错误界限(但它不是很好,因为你提供的示例应该是精确的),但是现在大多数不错的数学库都能够计算1参数{{1在1 ulp以内(最后一个单位),并施放到浮点和浮点数到1/2 ulp以内,总相对误差为3 ulps(因为这些都是乘法的),假设你的基数可以准确表示为float(即不是像log
这样的大整数。)
在python中,这将是:
log